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, and this page is about the one Vendor Central credentials get back: 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. fawcett splits the document into three tables accordingly — ten campaign columns, fourteen coupon columns, five ASIN columns — and this page documents all twenty-nine in that order. The coupon is the row most people mean when they ask about coupon performance, which is the grain the page carries.
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, fawcett attaches marketplace_id, country_code and snapshot_date to all three lake tables as context. 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 snapshot_date is the column a stored series would get its dates from. None of the three is in the column list on this page, 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. Trellis pulls it at daily granularity.
That is the trap, and it is the whole reason this report has its own page. 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. fawcett gives the vendor variant its own report key, sp_vendor_coupon_performance_report, precisely 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 fawcett validated against, 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 — fawcett's validated file 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.