Sample webhook payloads for AWS Marketplace agreement events
Agreement webhooks provide near real-time notifications for events related to your customers' AWS Marketplace agreements. Use these notifications to trigger provisioning workflows, update customer records, or adjust entitlement status in your systems.
AWS Only — Agreement webhooks are for AWS Marketplace only.
Subscribing to Agreement Webhooks
Agreement webhooks are delivered to the endpoint configured for your vendor account (or a product-level endpoint if one is set). See Create or Update Webhook to configure your endpoint.
Your endpoint must:
- Accept POST requests with Content-Type:
application/json - Return a
2xxHTTP status code (e.g.,200 OK) to acknowledge receipt - Respond within 10 seconds — offload long-running work to an async process
Event Types
| Event Type | Description |
|---|---|
agreement_registered | A customer's agreement has been successfully registered (Tackle-hosted or ISV-hosted). Use this to kick off provisioning and create customer records. |
agreement_changed | An agreement's status or terms have changed — for example, it was renewed, cancelled, or expired. Use this to keep your system in sync with the agreement lifecycle. |
agreement_license_updated | The License ARN associated with an agreement has been updated or deprovisioned. Use this to track license entitlement changes. |
Correlating Agreements With Your Systems
agreement_registered and agreement_changed both carry a tackle block with the private offer context for the agreement:
tackle.offer_id— the Tackle private offer id (po_id) the agreement originated from.tackle.offer_metadata— the Additional Fields configured on that private offer, forwarded exactly as they were entered.
If you record an internal identifier such as a CRM opportunity id in Additional Fields when the offer is created, it comes back on every agreement event for that offer. This lets you tie an agreement to the originating deal without maintaining your own offer-to-agreement mapping.
Both keys are always present. When an agreement has no Tackle private offer — a public offer accepted directly in AWS Marketplace, for example — offer_id is an empty string and offer_metadata is an empty object rather than being omitted.
Additional Fields are forwarded exactly as stored, which has two consequences worth coding for. Keys are the labels your team typed into Tackle, so they can contain spaces, punctuation and inconsistent casing (Quote Number, QuoteID, salesforce_offer_id). And an Additional Field that was left blank arrives as null, not as an empty string or a missing key — so read values defensively rather than assuming a string.
tackle.offer_idis notagreement.offer_id.tackle.offer_idis the Tackle private offer id (a UUID).agreement.offer_idis the AWS Marketplace offer id (offer-xxxxxxxxxxxxx). They identify different objects in different systems.
Looking for the License ARN?
The License ARN is not included in the agreement_registered or agreement_changed payloads. Subscribe to agreement_license_updated and read payload.license_arn.
Agreement Registered
Sent when a customer completes registration after accepting an AWS Marketplace offer.
Fields
| Field | Type | Description |
|---|---|---|
event_id | String | Unique identifier for this event notification. |
event_type | String | agreement_registered |
cloud | String | aws |
agreement.id | String | The unique identifier for the agreement. |
agreement.type | String | The type of agreement (e.g., PurchaseAgreement, VendorInsightsAgreement). |
agreement.status | String | The current status of the agreement (e.g., ACTIVE, ARCHIVED, CANCELLED, EXPIRED, RENEWED, REPLACED, ROLLED_BACK, SUPERSEDED, TERMINATED). |
agreement.start_time | String | The agreement's start timestamp in ISO 8601 format. |
agreement.end_time | String | The agreement's end timestamp in ISO 8601 format. Can be an empty string. |
agreement.acceptance_time | String | Timestamp when the customer accepted the offer in ISO 8601 format. |
agreement.acceptor_account_id | String | The AWS Account ID of the customer who accepted the agreement. |
agreement.proposer_account_id | String | The AWS Account ID of the vendor who proposed the agreement. |
agreement.product_id | String | The product's unique identifier. |
agreement.product_type | String | The type of product (e.g., SaaSProduct, AmiProduct, ContainerProduct, ProfessionalServicesProduct, MachineLearningProduct, DataProduct). |
agreement.offer_id | String | Identifier for the offer that created the agreement. |
agreement.offer_visibility | String | The visibility of the offer (e.g., Private). |
agreement.estimated_charges.total_amount | Number | The total estimated monetary value of the agreement. |
agreement.estimated_charges.currency_code | String | Three-letter ISO currency code for the estimated charges. |
tackle.vendor_id | String | The vendor identifier for the seller account in the Tackle Platform. |
tackle.vendor_name | String | The seller account's display name in the Tackle Platform. Empty string when unavailable. |
tackle.offer_id | String | The Tackle private offer id. Empty string when the agreement has no Tackle private offer. Not to be confused with agreement.offer_id, which is the AWS Marketplace offer id. |
tackle.offer_metadata | Object | The Additional Fields configured on the Tackle private offer, as key/value pairs. Keys are exactly as entered in Tackle, so they may contain spaces and mixed case. Values are strings, but an Additional Field left blank is sent as null — handle both. {} when the offer has no Additional Fields, or when there is no offer. |
tackle.registration.customer_id | String | The CustomerIdentifier from the ResolveCustomer API. Use this as the customer_id in the Tackle Metering API. |
tackle.registration.product_code | String | The ProductCode from the ResolveCustomer API. Use this as the product_id in the Tackle Metering API. |
tackle.registration.timestamp | String | Timestamp when registration occurred in ISO 8601 format. |
tackle.registration.details | Object | Key-value pairs of information collected from the buyer during registration. |
Example Payload
{
"event_id": "4e7b8c2d-9a0f-4b1e-8c3d-5f6a7b8c9d0e",
"event_type": "agreement_registered",
"cloud": "aws",
"agreement": {
"id": "agmt-4n5p6q7r8s9t0u1v",
"type": "PurchaseAgreement",
"status": "ACTIVE",
"start_time": "2023-01-01T12:00:00Z",
"end_time": "2024-01-01T11:59:59Z",
"acceptance_time": "2023-01-01T12:00:00Z",
"acceptor_account_id": "582039471625",
"proposer_account_id": "847201938475",
"product_id": "prod-k9l8m7n6p5q4",
"product_type": "SaaSProduct",
"offer_id": "offer-z1y2x3w4v5u6",
"offer_visibility": "Private",
"estimated_charges": {
"total_amount": 23456.78,
"currency_code": "USD"
}
},
"tackle": {
"vendor_id": "6A1I4NB",
"vendor_name": "ACME Software",
"offer_id": "32ed781f-aed6-46c6-87d4-15ffded0569c",
"offer_metadata": {
"Quote Number": "Q-09827989",
"Salesforce Opportunity ID": "0069000000ABcDeFGH",
"CPPO Partner": null
},
"registration": {
"customer_id": "91xM5j8zac1",
"product_code": "abc49bmwqw7js58uaw11dpxyz",
"timestamp": "2023-01-01T12:04:05Z",
"details": {
"Company": "ACME Corp",
"Email Address": "[email protected]",
"Full Name": "Steve Jones"
}
}
}
}Agreement Changed
Sent when an agreement's status or terms change. This covers updates, expirations, cancellations, renewals, and other lifecycle transitions.
Fields
| Field | Type | Description |
|---|---|---|
event_id | String | Unique identifier for this event notification. |
event_type | String | agreement_changed |
cloud | String | aws |
detected_at | String | Timestamp of when Tackle detected the change in ISO 8601 format. |
vendor_id | String | The vendor identifier for the seller account in the Tackle Platform. |
vendor_name | String | The seller account's display name in the Tackle Platform. Empty string when unavailable. |
tackle.offer_id | String | The Tackle private offer id. Empty string when the agreement has no Tackle private offer. Not to be confused with agreement.offer_id, which is the AWS Marketplace offer id. |
tackle.offer_metadata | Object | The Additional Fields configured on the Tackle private offer, as key/value pairs. Values are strings, but an Additional Field left blank is sent as null — handle both. {} when the offer has no Additional Fields, or when there is no offer. |
agreement.id | String | The unique identifier for the agreement. |
agreement.type | String | The type of agreement (e.g., PurchaseAgreement, VendorInsightsAgreement). |
agreement.status | String | The current status of the agreement (e.g., ACTIVE, ARCHIVED, CANCELLED, EXPIRED, RENEWED, REPLACED, ROLLED_BACK, SUPERSEDED, TERMINATED). |
agreement.start_time | String | The agreement's start timestamp in ISO 8601 format. |
agreement.end_time | String | The agreement's end timestamp in ISO 8601 format. |
agreement.acceptance_time | String | Timestamp when the customer accepted the offer in ISO 8601 format. |
agreement.acceptor_account_id | String | The AWS Account ID of the customer who accepted the agreement. |
agreement.proposer_account_id | String | The AWS Account ID of the vendor who proposed the agreement. |
agreement.product_id | String | The product's unique identifier. |
agreement.product_type | String | The type of product (e.g., SaaSProduct, AmiProduct, ContainerProduct, ProfessionalServicesProduct, MachineLearningProduct, DataProduct). |
agreement.offer_id | String | Identifier for the offer that created the agreement. |
agreement.offer_visibility | String | The visibility of the offer (e.g., Private). |
agreement.estimated_charges.total_amount | Number | The total estimated monetary value of the agreement. |
agreement.estimated_charges.currency_code | String | Three-letter ISO currency code for the estimated charges. |
agreement.terms.validity.duration | String | Duration of the agreement in ISO 8601 format (e.g., P24M). |
agreement.terms.payment_schedule | Object or null | Scheduled payment details. null if not applicable. |
agreement.terms.payment_schedule.currency_code | String | Three-letter ISO currency code for the payment schedule. |
agreement.terms.payment_schedule.schedule[] | Array | Array of scheduled charge objects. |
agreement.terms.payment_schedule.schedule[].charge_date | String | The date a payment is scheduled. |
agreement.terms.payment_schedule.schedule[].amount | Number | The amount for the scheduled charge. |
agreement.terms.upfront_payment | Object or null | One-time upfront payment details. null if not applicable. |
agreement.terms.upfront_payment.currency_code | String | Three-letter ISO currency code for the upfront payment. |
agreement.terms.upfront_payment.amount | Number | The total upfront payment amount. |
agreement.terms.upfront_payment.grants[] | Array | Entitlements granted with the upfront payment. |
agreement.terms.upfront_payment.grants[].dimension_key | String | The key for the granted entitlement. |
agreement.terms.upfront_payment.grants[].max_quantity | Integer | The maximum quantity for the granted entitlement. |
agreement.terms.usage_based | Object or null | Usage-based pricing details. null if not applicable. |
agreement.terms.usage_based.currency_code | String | Three-letter ISO currency code for usage-based rates. |
agreement.terms.usage_based.rates[] | Array | Array of usage dimension rate objects. |
agreement.terms.usage_based.rates[].dimension_key | String | The key for the usage dimension. |
agreement.terms.usage_based.rates[].price | Number | The price per unit for the dimension. |
agreement.terms.recurring_payment | Object or null | Recurring payment details. null if not applicable. |
agreement.terms.recurring_payment.currency_code | String | Three-letter ISO currency code for the recurring payment. |
agreement.terms.recurring_payment.billing_period | String | Billing frequency (e.g., Monthly). |
agreement.terms.recurring_payment.price | Number | The price per billing period. |
agreement.terms.variable_payment | Object or null | Pay-as-you-go terms with a spend ceiling. null if not applicable. |
agreement.terms.variable_payment.currency_code | String | Three-letter ISO currency code for the variable payment. |
agreement.terms.variable_payment.max_total_charge_amount | Number | The maximum total amount that can be charged under the agreement. |
agreement.terms.variable_payment.payment_request_approval_strategy | String | How payment requests are approved (e.g., AutoApprove). |
agreement.terms.variable_payment.expiration_duration | String | How long a payment request remains valid, in ISO 8601 format. |
agreement.terms.configurable_upfront_payment | Object or null | Configurable upfront payment details. null if not applicable. |
agreement.terms.configurable_upfront_payment.currency_code | String | Three-letter ISO currency code. |
agreement.terms.configurable_upfront_payment.selection.duration | String | Duration selected by the customer in ISO 8601 format. |
agreement.terms.configurable_upfront_payment.selection.dimensions[] | Array | Dimensions chosen by the customer. |
agreement.terms.configurable_upfront_payment.selection.dimensions[].key | String | The dimension key. |
agreement.terms.configurable_upfront_payment.selection.dimensions[].quantity | Integer | The quantity chosen for the dimension. |
agreement.terms.free_trial | Object or null | Free trial terms. null if not applicable. |
agreement.terms.free_trial.duration | String | Duration of the free trial in ISO 8601 format (e.g., P30D). |
agreement.terms.free_trial.grants[] | Array | Entitlements granted during the free trial. |
agreement.terms.free_trial.grants[].dimension_key | String | The key for the granted entitlement. |
agreement.terms.free_trial.grants[].max_quantity | Integer | The maximum quantity for the trial entitlement. |
agreement.terms.renewal.auto_renews | Boolean | Whether the agreement is configured to auto-renew. |
agreement.terms.legal.documents[] | Array | Legal documents associated with the agreement. |
agreement.terms.legal.documents[].type | String | The type of legal document (e.g., CustomEula, StandardEula). |
agreement.terms.legal.documents[].url | String | URL to the legal document. |
agreement.terms.support.refund_policy | String | The stated refund policy for the agreement. |
Example Payload
{
"event_id": "evt_1a2b3c4d5e6f7g8h",
"event_type": "agreement_changed",
"detected_at": "2025-10-15T10:05:00Z",
"cloud": "aws",
"vendor_id": "6A1I4NB",
"vendor_name": "ACME Software",
"tackle": {
"offer_id": "32ed781f-aed6-46c6-87d4-15ffded0569c",
"offer_metadata": {
"Quote Number": "Q-09827989",
"Salesforce Opportunity ID": "0069000000ABcDeFGH",
"CPPO Partner": null
}
},
"agreement": {
"id": "agmt-a1b2c3d4e5f6g7h8",
"type": "PurchaseAgreement",
"status": "ACTIVE",
"start_time": "2025-10-15T10:00:00Z",
"end_time": "2026-10-15T09:59:59Z",
"acceptance_time": "2025-10-14T18:30:00Z",
"acceptor_account_id": "123456789012",
"proposer_account_id": "987654321098",
"product_id": "prod-xyz789",
"product_type": "SaaSProduct",
"offer_id": "offer-pqr456",
"offer_visibility": "Private",
"estimated_charges": {
"total_amount": 50000.00,
"currency_code": "USD"
},
"terms": {
"validity": {
"duration": "P12M"
},
"payment_schedule": {
"currency_code": "USD",
"schedule": [
{
"charge_date": "2025-10-15T10:00:00Z",
"amount": 25000.00
},
{
"charge_date": "2026-04-15T10:00:00Z",
"amount": 25000.00
}
]
},
"usage_based": {
"currency_code": "USD",
"rates": [
{
"dimension_key": "api_calls",
"price": 0.01
},
{
"dimension_key": "storage_gb",
"price": 0.50
}
]
},
"recurring_payment": {
"currency_code": "USD",
"billing_period": "Monthly",
"price": 100.00
},
"upfront_payment": null,
"variable_payment": null,
"configurable_upfront_payment": null,
"free_trial": null,
"renewal": {
"auto_renews": true
},
"legal": {
"documents": [
{
"type": "CustomEula",
"url": "https://s3.amazonaws.com/vendor-eulas/eula-agmt-a1b2c3d4.pdf"
}
]
},
"support": {
"refund_policy": "No refunds after 30 days."
}
}
}
}Agreement License Updated
Sent when the License ARN associated with an agreement is updated or deprovisioned.
Fields
| Field | Type | Description |
|---|---|---|
event_id | String | Unique identifier for this event notification. |
event_type | String | agreement_license_updated |
cloud | String | aws |
detected_at | String | Timestamp of when Tackle detected the change in ISO 8601 format. |
vendor_id | String | The vendor identifier for the seller account in the Tackle Platform. |
payload.status | String | The license status (e.g., updated, deprovisioned). |
payload.acceptor_account_id | String | The AWS Account ID of the customer who accepted the agreement. |
payload.agreement_id | String | The unique identifier for the agreement. |
payload.license_arn | String | The License ARN associated with the agreement. |
payload.offer_id | String | The unique identifier for the AWS offer. |
payload.product_id | String | The unique identifier for the AWS product. |
payload.proposer_account_id | String | The AWS Account ID of the vendor who proposed the agreement. |
Example Payload
{
"event_id": "evt_1a2b3c4d5e6f7g8h",
"event_type": "agreement_license_updated",
"detected_at": "2025-10-15T10:05:00Z",
"cloud": "aws",
"vendor_id": "6A1I4NB",
"payload": {
"status": "updated",
"acceptor_account_id": "533037066560",
"agreement_id": "agmt-ab5hndndgx4nccbn1avg6n0nk",
"license_arn": "arn:aws:license-manager::294406891311:license:l-dde70b00f82f4ddb84ccd578e7b72427",
"offer_id": "offer-4kzrsiu5mlyfo",
"product_id": "prod-cice7vg3kyn3a",
"proposer_account_id": "686371838774"
}
}