← Recipes

Reference · fact-checked 2026-06-10

Engineering reference

Listing, buying, and licensing a product on AWS Marketplace programmatically

Agent-readable version

Plain markdown at /recipes/aws-marketplace-api.md. Fetch with one curl, ingest with any LLM tool, license CC0.

curl -O https://agledger.ai/recipes/aws-marketplace-api.md

A complete, vendor-neutral reference for doing AWS Marketplace end-to-end through APIs instead of the console: assembling and publishing a container listing (Catalog API), buying it for testing (Discovery + Agreements APIs), and enforcing entitlement at runtime (License Manager or the Metering Service). Every operation, IAM permission, region constraint, and error mapping below is drawn from AWS documentation or confirmed against a live API run.

In short: which APIs do what

To operate an AWS Marketplace product programmatically you use four distinct services, not one:

All AWS Marketplace API operations run in us-east-1.

Which service owns which operation?

ServiceSDK client / CLISideOwns
Catalog API@aws-sdk/client-marketplace-catalog · aws marketplace-catalogSellerStartChangeSet, DescribeChangeSet, ListChangeSets, CancelChangeSet, ListEntities, DescribeEntity, TagResource/UntagResource/ListTagsForResource
Discovery API (Apr 2026)@aws-sdk/client-marketplace-discovery · aws marketplace-discovery(CLI ≥ 2.34.27)BuyerSearchListings, SearchFacets, GetListing, GetProduct, ListPurchaseOptions, GetOfferSet, GetOffer, GetOfferTerms, ListFulfillmentOptions
Agreements API (May 2026)@aws-sdk/client-marketplace-agreement · boto3 marketplace-agreementBuyerCreateAgreementRequest, AcceptAgreementRequest, DescribeAgreement, SearchAgreements, GetAgreementTerms, GetAgreementEntitlements, ListAgreementCharges, UpdatePurchaseOrders, cancellation/payment requests
AWS License Manageraws license-managerBuyer runtimeCheckoutLicense, CheckInLicense, GetLicense, ListReceivedLicenses
Marketplace Metering Service@aws-sdk/client-marketplace-metering · aws meteringmarketplaceBuyer runtimeRegisterUsage, MeterUsage, BatchMeterUsage
Marketplace Entitlement Serviceaws marketplace-entitlementSellerGetEntitlements

The Discovery and Agreements procurement APIs were absent from aws-cli 2.33.x and arrived in later releases: Discovery in aws marketplace-discovery(≥ 2.34.27), and the procurement calls (create-agreement-request / accept-agreement-request) in aws marketplace-agreement(≥ 2.34.43). The read-only agreement commands (describe-agreement, search-agreements, get-agreement-terms) predate both. SDK clients are an equivalent alternative on any version.

Do I need AWS License Manager or the Marketplace Metering Service?

It is determined by product type × pricing model, not by preference — and wiring to the wrong service for your pricing model fails in production even when unit tests pass.

Product typePricing modelIntegrationEntitlement checkMetering / drawdown
ContainerFree / hourly / fixed-monthlyMetering ServiceRegisterUsage (also gates startup)AWS meters automatically
ContainerUsage / custom dimensionsMetering ServiceMeterUsageyou emit usage per dimension
ContainerContract (upfront)License ManagerCheckoutLicenseunits are floating, not metered
ContainerContract with consumption (drawdown)License ManagerCheckoutLicenseeach checkout draws down counted units
AMIhourly / annual / BYOL / contractMetering Service or License ManagerRegisterUsage / CheckoutLicenseMeterUsage for custom
SaaSsubscription / contract / usageSaaS Fulfillment v2 + Metering ServiceResolveCustomer→ activateBatchMeterUsage

The two “not entitled” errors differ: the License Manager path returns NoEntitlementsAllowedException; the Metering Service path returns CustomerNotEntitledException. They are not interchangeable.

How do I list and update a product through the Catalog API?

Every seller-side change is an asynchronous change set against an entity (your product). The pattern is always: call StartChangeSet, get back a ChangeSetId, then poll DescribeChangeSet until it reaches a terminal status. Use DetailsDocument (native JSON); the older Details string form is legacy.

The change types you assemble a listing from:

Field limits worth pre-validating: Title ≤ 72, ShortDescription ≤ 1000, LongDescription ≤ 5000, Highlights ≤ 3, SearchKeywords ≥ 1 (≤ 250 combined characters), Categories ≤ 3. The ChangeSetName must match ^[\w\s+=.:@-]{1,100}$— note that parentheses are not allowed.

What are the change-set status values, and when can I cancel?

DescribeChangeSet returns one of: PREPARINGAPPLYING SUCCEEDED, or CANCELLED / FAILED (a FailureCode such as CLIENT_ERROR, plus per-change ErrorDetailList).

Container-listing rules that reject change sets

How do I publish a Limited product to Public?

Publishing is a single UpdateVisibility change on the product with DetailsDocument: {"TargetVisibility": "Public"} — but it is the step AWS gates most heavily:

The review checks copy completeness, logo, EULA and refund policy, real pricing, usage instructions that actually work end-to-end, and License Manager integration behavior. Because that last point is verified against a real purchase, it pays to test the buyer experience before submitting (next section).

How do I buy or test my own listing programmatically (no console)?

A seller can subscribe to its own Limited-visibility product (proposer and acceptor on the same account works), which is the supported way to test the full purchase-and-entitlement path. The documented cheap-test pattern: keep the product Limited, drop every rate card to $0.01 with one UpdatePricingTerms change set, buy it, validate, then restore the exact original pricing (save the full original terms JSON and re-apply it, since UpdatePricingTerms replaces wholesale).

The buyer flow combines Discovery (read) and Agreements (purchase):

  1. GetOffer(offerId) (Discovery) → the agreementProposalId (at-…), seller of record, pricing model.
  2. GetOfferTerms(offerId)(Discovery) → the term IDs (pricing, legal, support, renewal) and live rate cards.
  3. CreateAgreementRequest({ intent: 'NEW', agreementProposalIdentifier, requestedTerms: [...] }) (Agreements) → an agreementRequestId (ar-…) and a chargeSummary that shows the exact charge before you commit. The pricing term carries the selected duration and dimension quantity; legal/support terms are accepted bare; the renewal term sets auto-renew.
  4. AcceptAgreementRequest({ agreementRequestId }) (Agreements) → the agreementId (agmt-…). This is the point money moves.

What is the readiness signal after purchase?

Poll GetAgreementEntitlements (Agreements API) until it reports PROVISIONED — typically about 90 seconds; the agreement itself is ACTIVE immediately on accept. Do not poll the seller-side marketplace-entitlement get-entitlements, which can lag much longer and make a ready entitlement look absent. The License Manager license and grant appear shortly after PROVISIONED.

A fresh buyer account also needs the License Manager service-linked role before any checkout succeeds, or every call fails with “Service role not found”:

aws iam create-service-linked-role --aws-service-name license-manager.amazonaws.com

How do I check entitlement at runtime (contract pricing / License Manager)?

For a container product with contract pricing, your software calls CheckoutLicense at startup to prove the running customer bought it. The semantics that trip up most integrations:

Runtime IAM needs license-manager:CheckoutLicense, CheckInLicense, GetLicense, ListReceivedLicenses, and ExtendLicenseConsumption(the last extends a floating checkout past its TTL), with credentials supplied by the runtime (ECS task role, EKS IRSA, or instance profile) — never baked into the image.

How do I check entitlement at runtime (usage pricing / Metering Service)?

For usage or hourly pricing, the Metering Service both verifies entitlement and meters usage:

What IAM permissions does each side need?

Seller (Catalog API): the AWSMarketplaceSellerFullAccess managed policy (full Catalog write) or AWSMarketplaceSellerProductsReadOnly (read-only). For least privilege, grant aws-marketplace:StartChangeSet on the entity ARN plus a ChangeSet ARN with a /* wildcard (a fresh change-set ID is minted per request, so the wildcard is required), and optionally scope by change type with the catalog:ChangeType condition key. Resource-level permissions for StartChangeSet work only through the Catalog API, not the Management Portal console.

Buyer (procurement): the aws-marketplace:* agreement/discovery actions (e.g. CreateAgreementRequest, AcceptAgreementRequest).

Buyer (runtime): for contract products, license-manager:CheckoutLicense, CheckInLicense, GetLicense, ListReceivedLicenses, and ExtendLicenseConsumption, plus the License Manager service-linked role; for usage products, the metering actions.

Error reference: what each Marketplace error actually means

AWS Marketplace errors are terse and often overloaded onto one string. The mappings:

ErrorService / phaseWhat it means
NoEntitlementsAllowedExceptionLicense Manager checkoutSeveral causes behind one string: wrong ProductSKU (must be the product ID), wrong Unit, a CheckoutType mismatched to the license (use PROVISIONAL for a floating license), the counted entitlement exhausted, or the entitlement not yet propagated
CustomerNotEntitledExceptionMetering ServiceBuyer not subscribed (usage/metering path)
ValidationException: Invalid request client tokenLicense Manager checkoutA ClientToken was reused; it is accepted once, then rejected for the rest of the UTC day. Use a fresh randomUUID() per attempt
InvalidRegionExceptionMetering ServiceSDK pinned to a region other than where the task launched. Obtain region at runtime
PlatformNotSupportedExceptionMetering ServiceCalled off ECS/EKS/Fargate (e.g. local dev)
ResourceInUseException (HTTP 423)Catalog APIEntity is locked by an in-flight change set
MISSING_SELLER_PROFILE_INFORMATIONCatalog UpdateVisibilityNo public seller profile on the account
AUDIT_ERRORCatalog UpdateVisibilitySeller-Ops manual review failed
UNSUPPORTED_CONTAINER_IMAGE_URICatalog AddDeliveryOptionsImage isn't a plain Docker Image Manifest V2 (e.g. a Sigstore/attestation artifact pushed to Marketplace ECR)
INVALID_USAGE_INSTRUCTIONSCatalog AddDeliveryOptionsNon-ASCII characters in usage-instruction text
CLIENT_ERROR (FailureCode)CatalogMalformed change set; inspect per-change ErrorDetailList

FAQ

Is the AWS Marketplace ProductSKU the product ID or the product code?

The product ID (prod-…), not the product code (eq9fe4…). The issued license carries the product ID in its ProductSKU field and CheckoutLicense matches on it — passing the product code returns NoEntitlementsAllowedException for every customer.

Why does CheckoutLicense return NoEntitlementsAllowedException?

Several causes behind one string: the product code instead of the product ID in ProductSKU; the wrong Unit (a floating entitlement is Count, not None); a CheckoutType mismatched to the license (a floating license needs PROVISIONAL); a counted entitlement still held by a prior checkout’s TTL; or an entitlement that has not propagated yet. Diagnose by calling GetLicense on the issued license and diffing the real ProductSKU, Entitlements, and ConsumptionConfiguration against your request.

Why does CheckoutLicense fail with Invalid request client token?

The ClientToken was reused. License Manager accepts a token once, then rejects every reuse for the rest of the UTC day, across processes. Generate a fresh randomUUID() per attempt.

What CheckoutType do AWS Marketplace contract licenses use?

It depends on the license configuration. Floating/tiered contract licenses (configured with a ProvisionalConfiguration TTL — the common entitlement-check pattern) check out with PROVISIONAL; drawdown/consumption licenses use PERPETUAL. Checking out a floating license with PERPETUAL returns NoEntitlementsAllowedException, so match the type to the license.

Do I need AWS License Manager or the Marketplace Metering Service?

Contract (upfront) pricing uses License Manager (CheckoutLicense); usage/hourly/custom-metering pricing uses the Metering Service (RegisterUsage or MeterUsage). The not-entitled errors differ accordingly: NoEntitlementsAllowedException vs CustomerNotEntitledException.

Can a seller buy its own AWS Marketplace listing to test it?

Yes. A seller can subscribe to its own Limited-visibility product (proposer and acceptor on the same account). The documented test pattern is to temporarily reduce price via UpdatePricingTerms, purchase, then restore.

How do I test an AWS Marketplace listing cheaply?

Keep the product Limited, drop every rate card to $0.01 with one UpdatePricingTerms change set, buy it, validate, then restore the exact original pricing (save and re-apply the full original terms JSON, since the operation replaces wholesale).

How do I programmatically subscribe to an AWS Marketplace product?

Read the offer with the Discovery API (GetOffer → proposal ID, GetOfferTerms → term IDs), then purchase with the Agreements API: CreateAgreementRequest (returns a chargeSummary showing the exact price before you commit) → AcceptAgreementRequest. Both are us-east-1.

What is the readiness signal that a Marketplace entitlement is usable after purchase?

GetAgreementEntitlements reporting PROVISIONED (typically ~90 seconds). Do not poll the seller-side marketplace-entitlement get-entitlements, which lags.

Does the AWS CLI support the Marketplace Agreements and Discovery APIs?

Yes, in recent releases: Discovery in aws marketplace-discovery (≥ 2.34.27) and the Agreements procurement calls in aws marketplace-agreement (≥ 2.34.43); the read-only agreement commands predate both. aws-cli 2.33.x has neither procurement surface. SDK clients (@aws-sdk/client-marketplace-discovery, @aws-sdk/client-marketplace-agreement, boto3, or Go) work on any version.

How long does "Make Public" (UpdateVisibility) take on AWS Marketplace?

Up to 37 days. It must be a standalone change set, triggers a manual Seller-Ops review, and locks the product against all other change sets for the entire window. It can be cancelled while still PREPARING, before the audit begins; failures return AUDIT_ERROR.

Why does AddDeliveryOptions fail with UNSUPPORTED_CONTAINER_IMAGE_URI?

Marketplace ECR accepts plain Image Manifest V2 images only. Sigstore signatures, SLSA/attestation artifacts, and OCI referrer artifacts break it. Mirror the image by digest; keep supply-chain artifacts on your public registry.

Why does my usage-instructions change set fail with INVALID_USAGE_INSTRUCTIONS?

Non-ASCII characters. An em-dash, smart quotes, or other Unicode triggers it — keep the field ASCII-only.

Is an AWS Marketplace container contract license bound to a specific node or instance?

No. Any software on any container on any node can check out the license with the right credentials, which is why checking it back in immediately lets HA replicas and restarts each obtain it.

What does Expiration mean in the CheckoutLicense response?

The consumption-token TTL (checkout time plus the provisional TTL), not the contract end date. Read the contract end from the license’s Validity via GetLicense.

Why do my unit tests pass while AWS Marketplace licensing fails in production?

Mocks encode the same assumptions as the code under test, so a suite can assert the wrong contract (for example, that PROVISIONAL checkouts should be rejected) and stay green while the real integration is non-functional. The reliable check is running against a live entitlement, which the $0.01 self-purchase pattern makes cheap.

Sources