AWS Marketplace

Automate private offers using AWS Marketplace Catalog API

AWS Marketplace Catalog API lets sellers create private offers programmatically from their internal applications without needing to use the AWS Marketplace Management Portal (AMMP). Sellers can start by creating a draft private offer and iterate until the offer is ready for publishing.

AWS Marketplace sellers have raised the concern of frequently switching between internal applications and the AWS Marketplace user interface, creating a disjointed experience. The sellers must reconcile transactions manually between AWS Marketplace and their internal tools which can add additional time and budget. This manual process adds operational overhead, and is not scalable during periods of high volume. The AWS Marketplace APIs aim to solve these seller challenges.

In this post, we show you how to automate private offers within your internal applications using the AWS Marketplace Catalog API. You can extend the solution to create dashboards for managing private offers, which can be saved and cloned to create a new private offer quickly and programmatically.

Prerequisites

To follow along with the samples in this post, you must meet the following prerequisites:

  • Register as an AWS Marketplace seller.
  • To create a private offer, you must have an existing Amazon Machine Image (AMI), container, or software as a service (SaaS) product.
  • A basic understanding of JSON and Python programming language is necessary.

Solution overview

AWS Marketplace provides APIs for creating and managing catalog products, offers, and agreements. AWS Marketplace Catalog API also provides read and write actions to create, list, and manage private offers. The StartChangeSet write action creates change requests and if successful, returns the change set ID.

{

   "ChangeSetArn": "arn:aws:aws-marketplace:us-east-1:123456789012:AWSMarketplace/ChangeSet/changesetid12345a",

   "ChangeSetId": "changesetid12345a"

}

The change request is added to a queue and processed. The validation process can take anywhere from a few minutes to few hours.

For AWS Marketplace Catalog API read operations, use the DescribeChangeSet, ListEntities, and DescribeEntity actions. For Agreement API, use the SearchAgreements, DescribeAgreement, and GetAgreementTerms actions. The change set ID returned from the StartChangeSet action can be used to retrieve metadata and the latest update on the offer. You check the status of the change request with the DescribeChangeSet action.

AWS Marketplace Catalog API is integrated with Amazon EventBridge. The AWS Marketplace Catalog API sends an event to  Amazon EventBridge when a change request completes with a status of succeeded, failed, or cancelled. In addition, there are Amazon EventBridge notifications when a private offer is published and when it is accepted by a buyer.

Process diagram

A private offer in AWS Marketplace requires supplemental information including offer details, the buyer’s AWS account ID, End User License Agreement (EULA), pricing terms, and other change types. The following process diagram (Figure 1) shows the stages of private offer creation and corresponding change types.

Figure 1: Depicting stages of creating and updating private offers using AWS Marketplace Catalog API

Solution walkthrough: Automate private offers using AWS Marketplace Catalog API

This solution walkthrough shows you how to construct a private offer using AWS Marketplace Catalog API StartChangeSet action for a SaaS-based product with contract pricing. You will learn about updating pricing terms, listing, and managing private offers using various Catalog API actions.

A.   Construct CreateOffer change type

1.     Create a new JSON file to construct an offer using “CreateOffer” as ChangeType.

2.     Set ProductId of the SaaS product and Name for the offer.

{
            "ChangeType": "CreateOffer",
            "Entity": {
                "Type": "Offer@1.0"
            },
            "DetailsDocument": {
                "ProductId": "prod-1111111111111",
                "Name": "Test Private Offer"
            }
    }
3.     Save the JSON file.

4.     The JSON documents defined in sections B through E for each of the change types will be appended to this JSON file within the ChangeSet list element and run with the StartChangeSet action.

In the next step, create the change type for pricing terms.

B.   Construct UpdatePricingTerms change type

1.     Update the JSON document in the input file with “UpdatePricingTerms” as the ChangeType for a contract pricing model.

2.     Set the PricingModel as “Contract.”

3.     Set the Type for pricing term as “FixedUpfrontPricingTerm.”

4.    Set the DimensionKey and Price values.

{
    "ChangeType": "UpdatePricingTerms",
     "Entity": {
               "Type": "Offer@1.0",
               "Identifier": "$CreateOfferChange.Entity.Identifier"
      },
      "DetailsDocument": {
           "PricingModel": "Contract",
           "Terms": [{
                 "Type": "FixedUpfrontPricingTerm",
                 "CurrencyCode": "USD",
                  "Price": "0.0",
                  "Grants": [{
                     "DimensionKey": "BasicService",
                     "MaxQuantity": 1
                     },
                     {
                      "DimensionKey": "PremiumService",
                      "MaxQuantity": 1
                     }
                   ]
                }]
       }
    }

Save the JSON file and continue to update with the change types defined in following steps. In the next step, create the change type for payment terms.

C.   Construct UpdatePaymentScheduleTerms change type

The flexible payment scheduler enables you to extend a private offer with a custom payment schedule.

1.     Update the JSON document in the input file with the “UpdatePaymentScheduleTerms” ChangeType for a flexible payment schedule.

2.     Define schedule terms by updating ChargeDate and ChargeAmount values as shown in the following example:

{
      "ChangeType": "UpdatePaymentScheduleTerms",
      "Entity": {
           "Type": "Offer@1.0",
           "Identifier": "$CreateOfferChange.Entity.Identifier"
            },
            "DetailsDocument": {
                "Terms": [{
                  "Type": "PaymentScheduleTerm",
                  "CurrencyCode": "USD",
                  "Schedule": [
                    {
                      "ChargeDate": "2024-01-01",
                      "ChargeAmount": "200.00"
                     },
                     {
                       "ChargeDate": "2024-02-01",
                       "ChargeAmount": "170.00"
                      }
                   ]
                    }
                ]
            }
        }

Save the JSON file and continue to update with the change types defined in following steps. In the next step, create a change type for updating private offer, target buyer account, and legal terms.

D.   Construct UpdateInformation, UpdateTargeting, and UpdateLegalTerms

In this step, we implement the change types for updating offer information, target buyer account, and legal terms.

1.     Update the JSON document in the input file with the “UpdateInformationChangeType.

2.     Replace the offer Name and Description values in the JSON document.

{
     "ChangeType": "UpdateInformation",
     "Entity": {
         "Type": "Offer@1.0",
         "Identifier": "$CreateOfferChange.Entity.Identifier"
      },
      "DetailsDocument": {
         "Name": "New offer name",
         "Description": "New offer description"
      }
    }

3.    Update the JSON document in the input file with the “UpdateTargetingChangeType to target the private offer to the buyer’s AWS account.

4.    Replace the BuyerAccounts with the actual values of the target buyer accounts.

{

  "ChangeType": "UpdateTargeting",

  "Entity": {

      "Type": "Offer@1.0",

"Identifier": "$CreateOfferChange.Entity.Identifier"

   },

   "DetailsDocument": {

"PositiveTargeting": {

"BuyerAccounts":    ["123456789012",“111122223333”]

}

              }

 },

5.     Next, Update the JSON document in the input file with the “UpdateLegalTermsChangeType.

6.     Set the value of the Type field to “LegalTerm.”

7.     The Documents Type field accepts values of “CustomEula” or “StandardEula”. In this example, set the Documents Type value as “CustomEula.”

8.     Set the URL value to the S3 bucket object referencing the custom EULA document.

{

      "ChangeType": "UpdateLegalTerms",

      "Entity": {

          "Type": "Offer@1.0",

          "Identifier": "$CreateOfferChange.Entity.Identifier"

       },

       "DetailsDocument": {

           "Terms": [{

             "Type": "LegalTerm",

             "Documents": [{

               "Type": "CustomEula",

               "Url": "https://s3.amazonaws.com/sample-bucket/custom-eula.pdf"

               }]

            }]

        }

  }

Save the JSON file and continue to update with the change types defined in following steps.

E.   Release private offer

In this step, use the ReleaseOffer ChangeType to finalize the offer creation process and publish the offer.

1.     Update the JSON document in the input file with the “ReleaseOfferChangeType and save. All the change types you created in previous sections A through D should be consolidated into single ChangeSet list.

{
    "Catalog": "AWSMarketplace",
    "ChangeSet": [

        {

            :

            :

          #all ChangeTypes defined previously here.

          :

        },{
          "ChangeType": "ReleaseOffer",
          "Entity": {
            "Type": "Offer@1.0",
            "Identifier":"$CreateOfferChange.Entity.Identifier"
          },
          "DetailsDocument": {}
       }

   ]

   }

2.     Set the Catalog value as “AWSMarketplace

3.     Run the StartChangeSet action with AWS CLI using the JSON file you’ve constructed by following the previous sections.

4.     Upon successful validation and completion of the change request, the private offer is visible to the target buyer.

F.   List private offers

In this example, the ListEntities action retrieves a list of private offers from your AWS seller account using Python programming language.

1.     In the following Python code snippet, set the EntityType as “Offer” for the ListEntities action. Set the input Targeting filter with “BuyerAccounts” value.

response = mp_client.list_entities(
            "Catalog": "AWSMarketplace",
            "EntityType": "Offer",
            "EntityTypeFilters": {
               "OfferFilters": {
                    "Targeting": {
                         "ValueList": ["BuyerAccounts"]
                    }
               }

  },
  MaxResults=10,  # default 20 results returned.

)

2.     A successful response from the ListEntities action contains the list of private offers.

G.   Get details of a private offer

In this example, the DescribeEntity action retrieves the details of an offer from your AWS seller account using Python programming language.

1.     In the following Python code snippet, set the EntityId value with a private offer entity ID.

response = mp_client.describe_entity(
            Catalog="AWSMarketplace",
            EntityId="offer-111111111"
 )

A successful response from the DescribeEntity action contains the details of the private offer.

H.   Extend the availability date of private offer

1.     Create a JSON file for the UpdateAvailability changeType to set the expiry date that controls discoverability and purchase of the private offer.

2.    To extend the private offer, replace Identifier with the offer ID and set the AvailabilityEndDate in YYYY-MM-DD format to a future date.

{
    "Catalog": "AWSMarketplace",
    "ChangeSet": [
        {
            "ChangeType": "UpdateAvailability",
            "Entity": {
                "Type": "Offer@1.0",
                "Identifier": "offer-1111111111111"
            },
            "DetailsDocument": {
                "AvailabilityEndDate": "2026-01-01"
            }
        }
    ]
  }

3.     To expire the private offer, replace the Identifier with offer ID and set the AvailabilityEndDate to a past date in YYYY-MM-DD format.

{
    "Catalog": "AWSMarketplace",
    "ChangeSet": [
        {
            "ChangeType": "UpdateAvailability",
            "Entity": {
                "Type": "Offer@1.0",
                "Identifier": "offer-1111111111111"
            },
            "DetailsDocument": {
                "AvailabilityEndDate": "2022-01-01"
            }
        }
    ]
}

4.     Initiate StartChangeSet using the above JSON input file.

5.     Upon successful validation and completion of the StartChangeSet action, the private offer is extended or expired based on the input AvailabilityEndDate.

I.    Buyer accepts private offer

Each private offer has pricing and licensing terms specifically targeted to a buyer’s account. The seller of the product extends a private offer, and the offer has a set expiration date.

1. To view the private offers page, the AWS Marketplace buyer requires the permissions listed in the AWS Marketplace Buyer Guide.

2. The AWS Marketplace buyer can view and subscribe to the private offer using one of the following options:

J.   Agreement

An AWS Marketplace agreement is created when a buyer accepts a private offer. Agreements are a set of terms from the offer document that the buyer has accepted. Each agreement is uniquely identified in the AWS Marketplace agreement service by an agreement ID.

You can search agreements using SearchAgreements API, based on one of the following input criteria:

For a given agreement identifier, DescribeAgreement action provides details about the agreement.

The GetAgreementTerms action returns the agreement terms and automatic renewal indicator for a given agreement identifier.

K.   Change agreement with replacement offer

The replacement offer is a mechanism for making changes to existing agreements for SaaS contracts and SaaS contracts with consumption pricing models. A replacement offer is used to negotiate a change, renew an agreement, or make changes to the flexible payment schedule.

1.     As a seller, you create an upgrade offer in the draft state by calling the StartChangeSet action with CreateReplacementOffer change type.

2.    Replace the Identifier with offer ID, offer Name, and populate the pre-existing AgreementID, as shown in the following example.

{
 "Catalog": "AWSMarketplace",
 "ChangeSet": [
    {
        "ChangeType":"CreateReplacementOffer",
        "Entity":{
            "Type": "Offer@1.0",
            "Identifier": "offer-123456789"
        },
        "DetailsDocument": {
            "AgreementId": "agreement-ssdkd1234567",
            "Name": "offer name"
        }
    }
  ]
}

3.     Upon successful validation and completion, AWS Marketplace Catalog API generates an offer in draft state. A draft offer is incomplete and not visible to buyers in AWS Marketplace.

4.    Initiate update change types as mentioned in sections B through E to complete the replacement offer. This validates the entire offer and makes your offer visible to buyers in AWS Marketplace.

5.     The buyer has the option to accept the updated offer or to continue to operate under the original agreement.

Conclusion

In this blog post, we showed you how to create and manage private offers using AWS Marketplace Catalog API. Extend this solution to create a dashboard for managing private offers and clone them to create new private offers.

Here are links to additional resources to help you learn more about AWS Marketplace Catalog API use cases for private offers.

Cleanup

  • Expire private offer by changing the AvailabilityEndDate to a past date, as explained in section H.
  • To remove private offers, submit a request to the operations team in the AWS Marketplace Management Portal.

About the authors

Olabanji Olabanji Soaga is a Partner Solutions Architect at AWS. He focuses on helping partners build Well-Architected solutions on the AWS Cloud, and he especially enjoys learning networking. Outside of work, he loves cooking traditional Nigerian dishes and going on new adventures with his family.
Chandrashekar Chandrashekar Vishweshwara is a Specialist Solutions Architect with AWS Marketplace. In this role, Chandrashekar helps sellers with onboarding products to AWS Marketplace. Outside of work, he spends time with his family and puppy, goes out for walks, or watches movies.