wc_create_coupon: create a coupon
Creates a discount code. It is live and redeemable as soon as it saves.
Arguments
| Argument | Required | Meaning |
|---|---|---|
code |
Yes | The code customers type |
discount_type |
No | percent, fixed_cart or fixed_product |
amount |
No | The discount value |
description |
No | Internal note |
date_expires |
No | When it stops working |
usage_limit |
No | Total redemptions allowed |
individual_use |
No | Prevent combining with other coupons |
product_ids |
No | Restrict to specific products |
dry_run |
No | Report without creating |
Only code is required. Everything that bounds the coupon is optional.
Permissions
Allow WooCommerce catalog writes open, plus manage_woocommerce or edit_shop_coupons.
The defaults are dangerous
A coupon created with only a code and an amount has:
- no expiry date — it works forever;
- no usage limit — it works any number of times;
- no minimum spend — because that field cannot be set through MCP at all;
- no per-customer limit — likewise unreachable;
- stacking allowed, unless you set
individual_use.
That is a code anyone who finds it can use repeatedly, on any order, indefinitely, alongside other discounts.
None of this raises a warning. The coupon simply works, generously.
Set date_expires and usage_limit on every coupon you create here, and treat the unreachable restrictions as a reason to finish the job in the WooCommerce admin.
discount_type changes what amount means
| Type | An amount of 10 means |
|---|---|
percent |
10% off |
fixed_cart |
10 off the cart total |
fixed_product |
10 off each qualifying product |
Getting this wrong is the expensive mistake in this chapter. On a €200 order, percent gives €20 away and fixed_cart gives €10 — and confusing them in the other direction, on a shop with high-value items, gives away far more.
State both explicitly:
Create a coupon SUMMER25, percent type, amount 25, expiring 31 August, limited to 100 uses.
If discount_type is omitted, WooCommerce applies its own default rather than inferring your intent from the amount.
Check the code is free first
Codes must be unique, and a trashed coupon still holds its code. So SUMMER25 can fail to be created because last year's version is sitting in the trash where the default listing does not show it.
List the coupons in every status and confirm SUMMER25 is not already taken.
The dry run only echoes
It returns would_create containing the arguments you sent — not a resolved coupon, not the defaults WooCommerce would apply, not a uniqueness check on the code.
So it confirms the assistant understood you. It does not confirm the coupon will be created, or what it will look like. Use it to check the type and amount agree with your intent, then verify properly by reading the coupon back after creating it.
individual_use should usually be on
Without it, a customer can stack this code with others. Campaign coupons that were each meant to be a modest discount compound into a large one.
Turn it on unless the offer is explicitly designed to combine.
product_ids restricts, but only positively
You can limit the coupon to specific products. You cannot exclude products, exclude sale items, or restrict by category — those settings are not exposed.
A percentage coupon on a shop with items already discounted will apply on top of those sale prices, and there is no way to prevent it from here.
After creating
- Read the coupon back and confirm every field, especially
discount_typeanddate_expires. - Add the restrictions MCP cannot set — minimum spend, per-user limit — in the WooCommerce admin.
- Test the code in a real cart, on a cheap order and an expensive one.
- Only then publicise it.
Step 3 is not optional for anything with a percentage discount.
Common problems
| Symptom | Cause |
|---|---|
| The write is refused | Catalog write gate closed |
pom_ai_mcp_wc_forbidden |
Missing manage_woocommerce or edit_shop_coupons |
| The code was rejected | It exists already, possibly in the trash |
| The discount is far larger than intended | discount_type mismatch |
| The coupon never stops working | No date_expires was set |
| It is being used repeatedly | No usage_limit was set |
| It combines with other offers | individual_use is off |
| A restriction you wanted is missing | Not settable through MCP; use the admin |
Related
wc_get_coupons— check the code is freewc_update_coupon- Create a coupon