What this report contains
This is the first-party coupon report. Amazon serves sellers and vendors from the same report type and answers each with a completely different document. The one Vendor Central credentials get back is a list of campaigns, each carrying a vendor_code, campaign-level total_clips and total_redemptions, and a nested list of coupons whose own asins[] hold the per-ASIN discount. The seller version is a flat list of coupons with no campaign layer and no vendor code at all.
Because of that nesting, one file is not one row grain. It is three: the campaign, the coupon inside it, and the discount applied to each ASIN inside that. The document splits into three tables accordingly — ten campaign columns, fourteen coupon columns, five ASIN columns — and all twenty-nine are documented in that order. The coupon is the row most people mean when they ask about coupon performance, and it is the primary grain of the three.
The columns fall into four groups. Identity and settings — campaign_name, name, website_message, is_subscribe_and_save, is_once_per_customer, the start and end timestamps. Engagement — clips and redemptions at the coupon level, total_clips and total_redemptions at the campaign level above it. Money — budget, budget_spent, budget_remaining, budget_percentage_used and total_discount, all in the campaign's currency_code. And the per-ASIN discount, discount_type and discount_amount, which is where a single coupon stops being a single number.
There is no reporting date column anywhere in the three tables. creation_date_time, last_updated_date_time, start_date_time and end_date_time are all lifecycle timestamps describing the coupon, not the period its counts cover. Reading the file is reading the state of your coupons at the moment you pulled it.
Because nothing in the document dates a row, a stored copy needs context columns of its own: a marketplace, a country and a snapshot date. Only the first has any counterpart in Amazon's document — the schema marks a campaign-level marketplaceId required, though it is not among the columns measured off the production file — and a snapshot date is where a stored series gets its dates from. None of the three is in the column list for this report, because none of them comes out of the report.
How to get it
Through the Selling Partner API, you request the report type GET_COUPON_PERFORMANCE_REPORT, poll it until Amazon has it ready, and download the JSON document. There is no separate vendor report type: the same identifier serves both, and it is the credentials on the request that decide which schema comes back.
That is the trap, and it is what makes the vendor variant worth documenting on its own. Code written against the seller response — a flat coupons[] array — does not merely lose detail on the vendor response, it finds nothing at all, because the vendor document's top level is campaigns[]. The two schemas share no envelope. Give the vendor variant its own report key and its own tables, so the two never land under one warehouse prefix and get read as one dataset.
The second trap is the nesting. The document has to be flattened three times, once per grain, and the ASIN rows only exist two levels down inside their coupon. A parser that reads campaigns[] and stops has the budget numbers but not a single ASIN.
There is a window on the request, and it is not the window you might expect. Amazon requires campaignStartDateFrom and campaignStartDateTo in reportOptions, and they select which campaigns come back — every campaign whose start date-time, meaning the earliest start of any of its coupons, falls inside the range, reaching up to two years back. They do not date the rows. The returned rows carry no data date range at all, so what you get is the current state of the campaigns you selected, and a history is still something you keep rather than something you request.
Sample rows
Illustrative values, not data from a real account. Shown to give the shape of the file.
| coupon_id | name | clips | redemptions | budget | budget_spent | budget_remaining | start_date_time | end_date_time | campaign_id |
|---|---|---|---|---|---|---|---|---|---|
| COUPON-EXAMPLE-01 | Fall Refresh 15% off | 12000 | 900 | 5000.00 | 3750.00 | 1250.00 | 2026-09-01T00:00:00Z | 2026-09-30T23:59:59Z | CAMPAIGN-EXAMPLE-01 |
| COUPON-EXAMPLE-02 | Kitchen Bundle 5 off | 4500 | 380 | 2000.00 | 1900.00 | 100.00 | 2026-09-05T00:00:00Z | 2026-09-19T23:59:59Z | CAMPAIGN-EXAMPLE-02 |
| COUPON-EXAMPLE-03 | S&S Boost 10% off | 8200 | 1150 | 6000.00 | 6000.00 | 0.00 | 2026-08-15T00:00:00Z | 2026-09-14T23:59:59Z | CAMPAIGN-EXAMPLE-03 |
| COUPON-EXAMPLE-04 | New Launch Trial 20% off | 300 | 12 | 1500.00 | 60.00 | 1440.00 | 2026-09-20T00:00:00Z | 2026-10-04T23:59:59Z | CAMPAIGN-EXAMPLE-04 |
| COUPON-EXAMPLE-05 | Holiday Preview 15% off | 0 | 0 | 2500.00 | 0.00 | 2500.00 | 2026-10-01T00:00:00Z | 2026-10-31T23:59:59Z | CAMPAIGN-EXAMPLE-05 |
Field reference
Main table
| Column | Type | Description |
|---|---|---|
campaign_id | string | The coupon campaign this row is. A campaign is the outer object in the vendor schema and the key every coupon and ASIN row carries back to it. |
campaign_name | string | The vendor-chosen name of the campaign. Internal only — the text a shopper sees is the coupon's website_message, not this. |
vendor_code | string | The vendor code the campaign belongs to. This column is the clearest marker that you are holding the first-party file; the seller variant of this report has no equivalent, and an account with several vendor codes gets rows for each. |
budget_type | string | Whether the budget is allocated independently for each coupon or shared across the campaign. Amazon's schema enumerates two values, PER_INDIVIDUAL_COUPON and SHARED_BUDGET, and this column decides which money columns are populated — the coupon table's budget and budget_remaining are present only on a PER_INDIVIDUAL_COUPON campaign. On a SHARED_BUDGET campaign the cap is the campaign's, and Amazon's schema keeps it in totalBudget, totalBudgetSpent and totalBudgetRemaining — none of which is among the columns in this file, so nothing here caps a shared-budget campaign. Read budget_type before reading any coupon's budget columns as complete. |
currency_code | string | The currency the campaign's money columns are denominated in. This is the only currency column in the schema, so coupon-level money — budget, budget_spent, budget_remaining, total_discount — inherits it from the campaign. |
is_subscribe_and_save | bool | Whether the campaign is a Subscribe and Save coupon rather than an ordinary one. Worth splitting on before comparing redemption rates, because the two are offered in different places and behave nothing alike. |
total_clips | int64 | Clips counted at the campaign level, across every coupon in the campaign. In the production file checked, each campaign held exactly one coupon, so this matched that coupon's clips — do not assume that holds for a campaign with several. |
total_redemptions | int64 | Redemptions counted at the campaign level, the companion to total_clips. A redemption is a coupon actually used at checkout, so this is always the smaller of the two. |
creation_date_time | timestamp_ms | When the campaign was created, in milliseconds. This is a lifecycle timestamp, not a reporting date — it does not tell you what period the clip and redemption counts cover. |
last_updated_date_time | timestamp_ms | When the campaign was last modified. Useful for spotting a campaign someone edited mid-flight, which is a common reason two snapshots of the same campaign disagree. |
coupons
| Column | Type | Description |
|---|---|---|
campaign_id | string | On a coupon row, the campaign the coupon belongs to. This is the join key back to the campaign grain, and the reason coupon rows must never be summed without grouping on it. |
coupon_id | string | The coupon itself — the identity of this row, and the key the per-ASIN rows carry. |
name | string | The coupon's name as the vendor set it. Internal, and distinct from two other names it is easily confused with — the campaign table's campaign_name, one grain up, and website_message on this same row, which is the only one a shopper ever sees. |
website_message | string | The text Amazon shows shoppers on the coupon badge and detail page. The only column in the file that records what the offer actually said, which makes it the one to check when a coupon underperformed for reasons the numbers do not explain. |
start_date_time | timestamp_ms | When the coupon starts running, in milliseconds. A coupon can exist in the file before this moment, with zero clips. |
end_date_time | timestamp_ms | When the coupon is scheduled to stop. Scheduled, not actual — a coupon whose budget is exhausted stops being offered before this date, and nothing in the row moves to say so. |
is_once_per_customer | bool | Whether a shopper may redeem the coupon only once. A hard cap on how far redemptions can run ahead of unique buyers, and worth checking before reading a low redemption rate as weak demand. |
clips | int64 | How many times shoppers clipped this coupon. A clip is intent — the shopper saved the offer — not a purchase, and is the denominator people usually want under redemptions. |
redemptions | int64 | How many times this coupon was actually redeemed. Bounded above by clips, since a coupon has to be clipped before it can be used. |
budget | decimal | The coupon's funding cap, in the campaign's currency_code. Amazon stops serving the coupon when redemptions have consumed it. |
total_discount | decimal | The total amount customers saved by redeeming the coupon. That is not what the coupon cost you — budget_spent is the vendor's side of it and includes clip and redemption fees, which is why the two columns differ. Both are gross, and include purchases that were later returned or cancelled. |
budget_spent | decimal | How much of budget has been consumed. Together with budget_remaining this is the honest answer to whether a coupon is still being shown. |
budget_remaining | decimal | What is left of budget. Expected to be budget minus budget_spent; a coupon at zero here has stopped, whatever end_date_time says. |
budget_percentage_used | float64 | The share of the allocated budget consumed, expressed as a percentage on a 0–100 scale rather than as a 0–1 fraction — Amazon's schema bounds it at 100 and pairs a budget_spent of 42.29 against a budget of 10000.00 with the value 0.4. The denominator follows budget_type — the coupon's own budget when budgets are per-coupon, the campaign's total budget when they are shared. |
asins
| Column | Type | Description |
|---|---|---|
campaign_id | string | On an ASIN row, the campaign the discount belongs to. Present so the deepest grain can be grouped without going through the coupon table. |
coupon_id | string | On an ASIN row, the coupon this discount belongs to. The join key to the coupon grain. |
asin | string | The ASIN the discount applies to. One coupon covers several ASINs — the production file checked held 30 ASINs across 28 coupons — so this is the level at which a coupon stops being one number. |
discount_type | string | What kind of discount the ASIN gets, which is what makes discount_amount readable. Amazon's schema enumerates two values, PERCENT_OFF_LIST_PRICE and AMOUNT_OFF_LIST_PRICE, and discount_amount is a percentage under the first and a currency value under the second. |
discount_amount | decimal | The size of the discount for this ASIN. Its unit depends on discount_type, so it is not comparable across rows until you have grouped on that column. |
Use cases
Separating a clip problem from a redemption problem. clips says shoppers saw the offer and saved it; redemptions says they bought. A coupon with heavy clips and thin redemptions has a price, availability or detail-page problem downstream of the offer, and discounting harder will not fix it. A coupon with few clips has a visibility problem instead, and the two calls are opposites.
Knowing which coupons actually stopped. budget_remaining at zero means Amazon has stopped serving the coupon regardless of what end_date_time says. Ranking live coupons by budget_remaining against the days left in their window is the only way to see, from the file alone, which ones will die early — on campaigns where budget_type is PER_INDIVIDUAL_COUPON, which are the only ones whose coupons carry a budget of their own.
Auditing discount depth per ASIN. The ASIN grain carries discount_type and discount_amount per asin, so a campaign that looks like one offer can be discounting individual items at very different depths. This is where an overspend usually comes from.
Splitting Subscribe and Save from ordinary coupons. is_subscribe_and_save separates two mechanics that convert nothing alike. Blending them gives an average redemption rate that describes neither.
Checking what the offer actually said. website_message is the shopper-facing text, and it is the only column that records the offer as it was presented. When two coupons with similar budgets performed very differently, this and is_once_per_customer are the first two columns to read.
Reconciling campaign totals to coupon rows. total_clips and total_redemptions sit at the campaign level, clips and redemptions at the coupon level. Summing the coupon rows within a campaign_id and comparing is a cheap integrity check on any pipeline that flattens this file.
Limitations and gotchas
One report type, two incompatible schemas. Sellers and vendors both pull GET_COUPON_PERFORMANCE_REPORT, and the documents share nothing but the name. Anything that stores both under one table, or infers the schema from the report type rather than from the account, will silently produce an empty or half-empty dataset for one of them.
Joining the three grains fans out the money. A coupon covering five ASINs becomes five rows when you join the coupon table to the ASIN table, and budget_spent is repeated on every one of them. Summing after that join multiplies your spend by the ASIN count. Aggregate the money at the coupon grain first.
It is a snapshot, not a series. With no reporting date in the file, the clip and redemption counts are one number per coupon as of the pull. Amazon describes that number as cumulative for the campaign up until the day prior to your request — so it is a running total, not a window, and it is final only once the campaign has been over for a day or more. A day-over-day trend has to be built by keeping the snapshots; comparing two pulls is the only way to get a delta, and a coupon edited between them will move for reasons the counts do not show.
total_discount and budget_spent are not interchangeable. Amazon defines the first as what customers saved and the second as what the vendor spent, fees included — two sides of the same redemption, separated by the clip and redemption fees. Both are gross of returns and cancellations. Pick one deliberately for any number you publish, and do not let a query switch between them.
Money has one currency column and it lives on the campaign. currency_code is a campaign column; every money column at the coupon grain inherits it. A pull spanning vendor codes in different marketplaces will mix currencies, and nothing at the coupon grain warns you.
Amazon's schema defines fields this file does not carry. The published vendorCouponReport schema has a few columns beyond the twenty-nine here — a per-coupon customer_segment, a promotions_api_mapping_id that cross-references the Promotions API, and the campaign-level total_budget, total_budget_spent and total_budget_remaining that hold a SHARED_BUDGET campaign's cap. The columns above are the ones measured off a real production file, and they are what you should expect to land. Do not write a pipeline that requires the others, and do not assume a shared-budget campaign's cap is recoverable from this report.
Vendor coupon numbers do not benchmark against seller ones. Different schema, different account type, different placement of the offer. Comparing a 1P redemption rate to a 3P one is comparing two reports that only share a name.
FAQ
They come from the same Amazon report type but are completely different documents. The vendor file is a list of campaigns, each holding a vendor code, campaign-level clip and redemption totals, its coupons, and the ASINs those coupons discount. The seller file is a flat list of coupons. Code that reads one finds nothing in the other.
A clip is a shopper saving the coupon to their account, so it measures interest in the offer. A redemption is the coupon being used at checkout. Redemptions are always the smaller number, and the gap between them is usually the most useful thing in the file.
Almost always budget. When budget remaining reaches zero Amazon stops serving the coupon, and the end date in the file does not change to reflect it. Check budget spent against budget rather than trusting the schedule.
No. There is no sales or units column at any of the three grains. It reports clips, redemptions, budget consumption and the per-ASIN discount. Attributing revenue to a coupon means joining these coupons and ASINs to a sales report yourself.
Not from a single pull. There is no reporting date column, so each pull is the state of your coupons at that moment. A daily series is built by storing snapshots and differencing them.
Because the per-ASIN grain is its own table. A coupon covering several ASINs has one coupon row and one row per ASIN, each with its own discount type and amount. Summing coupon-level money after joining to that table double-counts it.
Sources
Every researched claim on this page, and the Amazon or Walmart page it came from.
- marketplaces (not-published) — developer-docs.amazon.com/report-type-values-performance — the Vendor Coupons Performance Report entry carries `Availability: Vendors` and the Brand Analytics role and no `Amazon store availability` line at all. developer-docs.amazon.com/sp-api-vendor-use-cases lists GET_COUPON_PERFORMANCE_REPORT under Performance with no store either, and the `vendorCouponReport` schema names none. The silence is Amazon's own, not a gap in the search: the reference writes an `Amazon store availability` line wherever it has one, and writes nothing where it does not — on developer-docs.amazon.com/report-type-values-fba the FBA Multi-Country Inventory Report (`GET_AFN_INVENTORY_DATA_BY_COUNTRY`) reads `Amazon store availability: Europe (EU)` while the FBA Inventory Report (`GET_AFN_INVENTORY_DATA`) directly above it has no such line. So `marketplaces` is `not-published`: Amazon does not say where this report exists.
- history_window — developer-docs.amazon.com/report-type-values-performance — the Vendor Coupons Performance Report entry lists among its report behaviors "This report supports start dates up to two years before the current date", and the dates in question are the campaign start date-times the request selects on. The same sentence closes the schema description in github.com/vendorCouponReport.json
- latency — developer-docs.amazon.com/report-type-values-performance — the same entry states "Data for this report is updated on a daily basis, so some fields might not reflect the most up-to-date state of the campaign", that an in-progress campaign gives "cumulative data for the campaign up until the day prior to your report request", and that the report is complete for a campaign that ended one day or more before the request.
- latency — github.com/vendorCouponReport.json — `lastUpdatedDateTime` is "The latest date-time the campaign data in this report was updated. May be up to 24 hours before the current date-time."
- latency, restatement (not found): neither — developer-docs.amazon.com/report-type-values-performance nor github.com/vendorCouponReport.json says whether a figure Amazon has already published can move afterwards for any reason other than the campaign still running. Both are explicit that the counts are gross of returns and cancellations, so a return is not a restatement here. Amazon publishes nothing further; two consecutive pulls of the same ended campaign would settle it. No stability beyond what Amazon states is claimed.
- budget_type — github.com/vendorCouponReport.json — `budgetType` is a required campaign field, enum `PER_INDIVIDUAL_COUPON` and `SHARED_BUDGET`, described as "Whether the budget is allocated independently for each coupon or shared among all coupons." Coupon-level `budget` and `budgetRemaining` are documented as present only when `budgetType` is `PER_INDIVIDUAL_COUPON`; campaign-level `totalBudget`, `totalBudgetSpent` and `totalBudgetRemaining` only when it is `SHARED_BUDGET`.
- discount_type — github.com/vendorCouponReport.json — `discountType` is a required ASIN-level field, enum `PERCENT_OFF_LIST_PRICE` and `AMOUNT_OFF_LIST_PRICE`, "Whether the discount is given as a fixed amount or a percentage off the list price." `discountAmount` "Reflects a percentage when discountType is PERCENT_OFF_LIST_PRICE and a currency value when discountType is AMOUNT_OFF_LIST_PRICE."
- total_discount — github.com/vendorCouponReport.json — `totalDiscount` is "Total amount saved by customers redeeming the coupon" and `budgetSpent` is "Total amount spent by the vendor on the coupon, including clip fees and redemption fees". Both, with `redemptions` and `budgetRemaining`, are stated to be gross values including purchases that were returned or cancelled.
- budget_percentage_used — github.com/vendorCouponReport.json — "Percentage of the allocated budget that has been spent, equal to the budgetSpent divided by budget or campaign totalBudget as appropriate", typed number with minimum 0 and maximum 100. The schema's own example pairs `budgetSpent` 42.29 against `budget` 10000.00 with `budgetPercentageUsed` 0.4 — the percentage, not the 0–1 fraction.
- console path (not found): nothing on developer-docs.amazon.com, sell.amazon.com or advertising.amazon.com writes down where this report lives in Vendor Central, and vendorcentral.amazon.com is login-gated. The nearest public path Amazon publishes is a seller one — sell.amazon.com/seller-promotions says to "hover over Advertising in the Seller Central main menu and select Promotions" — which is the other console and the other schema, so it is not this report's path. Only the SP-API route is described, and a reviewer with Vendor Central access can add the console path.
- requested period (reconciled, cadence unchanged) — developer-docs.amazon.com/report-type-values-performance — "Requests must include the campaignStartDateFrom and campaignStartDateTo in the reportOptions. All campaigns with a start date-time that fall within the range ... will be included. The start date-time of a campaign is considered to be the earliest start date-time of any of its coupons." That is a filter on which campaigns come back, by campaign start date-time; it does not date the rows, and the reference names no reporting-period column. The rows themselves cover no requested period and carry no data date range, so both hold at once and `cadence: snapshot` — which describes the data's own period, not the request — is right. The "How to get it" section states the required window and what it selects.
- schema fields absent from the measured columns (conflict recorded, column list unchanged) — github.com/vendorCouponReport.json — campaign `required` includes `marketplaceId`; coupon `required` includes `customerSegment` ("The customer segment that the coupon is available to", examples "All (Default)", "Amazon Prime", "Amazon Student"); the schema also defines `promotionsApiMappingId`, `totalBudget` ("Only present when budgetType is SHARED_BUDGET"), `totalBudgetSpent` and `totalBudgetRemaining`. None of the six is among the 29 columns measured off a production file, and the measured file outranks the schema, so the column list is unchanged. Instead, the `budget_type` description records that a shared-budget campaign's cap lives in campaign columns this file does not carry, and "Limitations" records that the schema defines fields the file does not.
- marketplace_id as a column — github.com/vendorCouponReport.json — `marketplaceId`, "The marketplace the campaign is running in", is required on every campaign in Amazon's own document, so it is not only context a stored copy adds. `country_code` and `snapshot_date` have no counterpart in the schema.