> ## Documentation Index
> Fetch the complete documentation index at: https://aiodapp.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Create in test mode

> shopify_discount_publish creates a real Shopify discount that only applies to your store's test email address.

Creates the discount in Shopify for real — in **test mode**.

<Info>
  **Tool name:** `shopify_discount_publish` · **Previously:** `publish_discount` · **Writes to Shopify** · Marked destructive, so most clients will ask before every call
</Info>

## When to use it

Only when the merchant has actually asked for the discount to be created, or wants to try it on the live storefront before opening it to shoppers.

[Draft a discount](/docs/mcp-server/tools/shopify-discount-draft) covers everything up to that point and touches nothing. **A successful draft is not a reason to publish.**

## What "test mode" really means

It is not a dry run.

The discount genuinely exists in Shopify, and Shopify genuinely evaluates it at checkout. What makes it safe is that AIOD attaches an email condition when creating it, so it **only ever applies to the store's test email address** — returned to you as `testModeEmail`. Real shoppers are unaffected.

It stays that way until a person opens it in the AIOD editor and switches it to active. **No tool here can make that switch, activate a discount, or delete one.**

<Warning>
  **Passing `targetDiscountId` overwrites.** It replaces that discount's rule in Shopify and re-creates it in test mode — so a discount that was live for shoppers stops applying. That's why this tool is marked destructive. Confirm with the merchant, in words, before doing it.
</Warning>

## Parameters

| Name               | Type   | Required | What it does                                                                                      |
| ------------------ | ------ | -------- | ------------------------------------------------------------------------------------------------- |
| `config`           | object | **Yes**  | The discount, sparse. Same shape as [Draft a discount](/docs/mcp-server/tools/shopify-discount-draft). |
| `targetDiscountId` | string | No       | An existing discount to overwrite. Leave it out to create something new.                          |

There is no `mode` parameter. Test mode is fixed in the server — nothing a caller sends can push a chat-authored discount live.

## What comes back

### When it works

```json theme={null}
{
  "ok": true,
  "discountId": "clx8n2k9a0001abcd",
  "url": "https://admin.shopify.com/store/your-store/apps/aiod-automatic-discounts/app/bogo/clx8n2k9a0001abcd",
  "shopifyDiscountId": "gid://shopify/DiscountAutomaticNode/123456789",
  "title": "Summer BOGO — tees",
  "status": "TEST_MODE",
  "testModeEmail": "aiod-test-a1b2c3@example.com",
  "warnings": [],
  "message": "Created in TEST MODE. It is live in the store but only applies for the test email above — tell the merchant they must open it and switch it to active before real shoppers see it."
}
```

| Field               | What it is                                                       |
| ------------------- | ---------------------------------------------------------------- |
| `discountId`        | The AIOD id, usable with every other tool.                       |
| `url`               | Where the merchant goes to switch it from test mode to active.   |
| `shopifyDiscountId` | The Shopify discount that was created.                           |
| `testModeEmail`     | The only address the discount applies for. **Always show this.** |
| `warnings`          | Validation warnings that didn't block it.                        |

### When it's rejected

```json theme={null}
{
  "ok": false,
  "issues": [ { "level": "error", "code": "...", "message": "..." } ],
  "simulation": [ ... ],
  "message": "The discount did not pass validation or cart simulation, so nothing was created. Correct the affected paths and retry."
}
```

If validation or simulation fails, **nothing is created or changed.**

| Status                 | When                                                                             |
| ---------------------- | -------------------------------------------------------------------------------- |
| `400`                  | Missing or invalid `config`, unsupported template, or the publish itself failed. |
| `404`                  | `targetDiscountId` isn't one of this store's discounts.                          |
| `200` with `ok: false` | Validation or simulation rejected it.                                            |

## What it checks first

Exactly the same gate as drafting — shape repair, field policy, empty tier check, then validation and cart simulation. **An unverified configuration is never published.** The [rejection codes](/docs/mcp-server/tools#rejections-are-useful-not-fatal) are the same too.

## Things people ask that land here

* "Create it — I want to test the BOGO on the storefront."
* "Go ahead and publish the free gift offer in test mode."
* "Replace the tier ladder on my volume discount with these three tiers."

## Getting it right

Report all three of these, every time:

1. The discount is genuinely created in Shopify, in test mode.
2. It only applies for `testModeEmail`. Real shoppers see nothing.
3. The merchant must open `url` and switch it to active themselves. No tool can do it for them.

And remember this only covers AIOD's automatic discounts — not discount codes, and not discounts created directly in Shopify or by another app.
