Tools

Discounts

Thirteen tools for Shopify checkout discounts, managed as campaigns with one discount per store: read campaigns, capabilities, and exports; edit write drafts that never reach Shopify; and the publish-tier commands that change live discounts. They call the same validation, revisions, and publish locks as the Discounts pages, and are available only to accounts with the Discounts feature.

Plan name → tool

Tool names follow the catalog's <verb>_<subject>_v1 convention. The approved plan named the operations differently; this table maps them.

Plan nameToolTier
discount_listlist_discounts_v1read
discount_getget_discount_v1read
—get_discount_capabilities_v1read
discount_createcreate_discount_v1write
discount_update_storeupdate_discount_store_v1write
discount_update_sharedupdate_discount_shared_v1write
discount_add_storeadd_discount_store_v1write
discount_duplicateduplicate_discount_v1write
discount_publishpublish_discount_v1publish
discount_lifecycleset_discount_lifecycle_v1publish
discount_recreaterecreate_discount_v1publish
discount_deletedelete_discount_v1publish
export toolsexport_discounts_v1read
The one delete, and why it is publish-tier.

delete_discount_v1 removes store discounts from Shopify — the same kind of live store write as turning a discount off or replacing it — and deletes no product, collection, or other catalog item. It requires pim:publish, confirmed: true, and an explicit store list (or, for a campaign with no store left, delete_empty_campaign). The pim:delete permission stays ungrantable and still gates every catalog delete. The in-app assistant always asks before any publish-tier discount tool runs, and waits for the merchant's explicit confirmation, naming the stores, before it removes a discount. It treats these tools as available only where list_stores_v1 reports the discounts capability.

Customer identity never reaches a tool.

Customer and segment eligibility is returned as Shopify GIDs only. Looking up customer names is an in-app action, and its route is not reachable with an MCP token.

list_discounts_v1

list_discounts_v1pim:read

List the account's discount campaigns, one row per store with its method (code or automatic), type, title, Shopify status, publish state, dates, usage, code count, and ownership (native or external_app — another app's discount, read-only).

ArgumentTypeDescription
searchstringCampaign name or store title.
methodstring[]code, automatic.
familystring[]basic, bxgy, free_shipping, app (another app's discount).
shopify_statusstring[]ACTIVE, SCHEDULED, EXPIRED.
publish_statusstring[]never_published, pending, published, failed.
channel_idsstring[]Only campaigns on these stores.
page, page_sizeintegerPaging; page_size is clamped at 100.

get_discount_v1

get_discount_v1pim:read

Read one campaign and each store's version: its revision (the token every edit sends back), configuration fields, typed selections with whether Shopify confirmed them, buyer context as Shopify GIDs only (never customer names or emails), Shopify facts (status, usage, sales, summary, share links), whether it is editable, and its publish blockers.

ArgumentTypeDescription
idstring, requiredThe discount campaign id.

get_discount_capabilities_v1

get_discount_capabilities_v1pim:read

Per store: missing discount or customer permissions, shop currency and time zone, Shopify Plus, active automatic discounts against Shopify's limit, and customer lookup availability. Advisory only. Open world: refresh: true reads Shopify live; otherwise a snapshot up to 15 minutes old answers.

ArgumentTypeDescription
channel_idsstring[], requiredThe stores to check.
refreshbooleanRead Shopify live.

create_discount_v1

create_discount_v1pim:write

Create a campaign as a DRAFT on the listed stores, all of one method and type. A store whose draft is invalid is reported in failed with its field errors; nothing reaches Shopify until publish_discount_v1.

ArgumentTypeDescription
namestring, requiredThe campaign name (internal).
channel_idsstring[], requiredThe stores.
methodstring, requiredcode or automatic.
familystring, requiredbasic, bxgy, or free_shipping. Another app's type (app) is refused.
changesobjectFields, {key: value}: Title, Starts At / Ends At, and the JSON documents Discount Value, Minimum Requirement, Combines With, and the rest.
selection_modesobjectget, buy, buyer.
relationshipsobject{role: [item ids]}, e.g. discount_get_product.
external_contextobject{kind, ids}: customer or segment GIDs, one store only.
preferred_codesobjectCode per store.
scheduleobjectSame instant, same local time, or store local.

update_discount_store_v1

update_discount_store_v1pim:write

Save draft changes to one store's discount, validated exactly as the discount page does. revision is required; a stale one is refused with current_revision, and an invalid save is refused with field_errors and writes nothing. Listed selection roles replace that role's list. A method or type change on a discount already on Shopify needs recreate_discount_v1.

ArgumentTypeDescription
idstring, requiredThe discount campaign id.
channel_idstring, requiredThe store id; the discount must have a version on it.
revisioninteger, requiredFrom get_discount_v1.
changes, selection_modes, relationships, external_context, scheduleobjectAs for create_discount_v1.
currency_resolutionstringpreserve_nominal keeps amounts as written when currencies differ.

update_discount_shared_v1

update_discount_shared_v1pim:write

Apply one draft edit to several stores of a campaign at once. Each store saves on its own; the result lists stores saved and stores refused with reasons, so partial success is normal.

ArgumentTypeDescription
idstring, requiredThe discount campaign id.
master_revisioninteger, requiredThe campaign revision.
channel_idsstring[]The stores to edit. Leave empty to change only the campaign name or defaults; selection modes, selections, and a schedule need stores.
changed_keys, valuesstring[], objectThe fields to change and their values.
expected_revisionsobjectEach store version's revision.
name, selection_modes, relationships, schedule, update_defaultsOptional parts of the edit.

add_discount_store_v1

add_discount_store_v1pim:write

Add a draft version on another store, copied from one of the campaign's stores (selections remapped to that store's items; customer and segment choices never copied) or started from the campaign defaults. Selected items missing on the new store are refused with missing_targets unless accept_missing_targets is true.

ArgumentTypeDescription
idstring, requiredThe discount campaign id.
master_revisioninteger, requiredThe campaign revision.
channel_idstring, requiredThe store to add.
copy_from_channel_idstringThe store to copy.
method, family, changes, preferred_codeWithout a copy: the starting configuration (family as for create_discount_v1).
accept_missing_targetsbooleanCreate it anyway; the missing items become publish blockers.

duplicate_discount_v1

duplicate_discount_v1pim:write

Copy a campaign into a new draft campaign on the same stores (or a subset), without its Shopify identity, statistics, or codes.

ArgumentTypeDescription
idstring, requiredThe discount campaign id.
channel_idsstring[]Source stores to copy (default all).
namestringNew name (default "Copy of …").
preferred_codesobjectCode per store.

publish_discount_v1

publish_discount_v1pim:publish

Publish a campaign's drafts LIVE on the listed stores (default every store): creates the Shopify discount the first time and updates it after, then confirms it by reading it back. A store with blockers, a missing permission, an unpublished selected item, or changes made in Shopify since the last publish is refused on its own. Runs as a background operation; poll get_publish_operation_v1.

ArgumentTypeDescription
idstring, requiredThe discount campaign id.
channel_idsstring[]Restrict to these stores.

set_discount_lifecycle_v1

set_discount_lifecycle_v1pim:publish

Activate or deactivate a published discount on the listed stores. Shopify has no paused state: deactivating ends it now. Background operation.

ArgumentTypeDescription
idstring, requiredThe discount campaign id.
actionstring, requiredactivate or deactivate.
channel_idsstring[], requiredAt least one store.

recreate_discount_v1

recreate_discount_v1pim:publish

Change the method or type of a discount already on Shopify by replacing it: the new discount is created, the old one deleted, and its main code carried over. A code discount with more than one code in Shopify is refused: manage extra codes in Shopify. Usage history and share links are lost, with a short gap while the replacement takes over. Refused before anything changes when the draft is invalid or the revision is stale. Background operation.

ArgumentTypeDescription
idstring, requiredThe discount campaign id.
channel_idstring, requiredThe store id; the discount must have a version on it.
revisioninteger, requiredThe store version's revision.
method, familystring, requiredThe new type; family is basic, bxgy, or free_shipping.
changes, selection_modes, relationships, external_context, preferred_codeThe replacement's configuration.
confirmedboolean, requiredMust be true.

delete_discount_v1

delete_discount_v1pim:publish

Delete a campaign's discount from the listed stores: each store's Shopify discount, its codes, and its usage history are deleted, then the store version is removed from Peak PIM. It deletes no catalog item. Another app's discount is refused. A campaign with no store version left (stores is empty in get_discount_v1) is removed with delete_empty_campaign; nothing changes in Shopify. Background operation: poll get_publish_operation_v1.

ArgumentTypeDescription
idstring, requiredThe discount campaign id.
channel_idsstring[]At least one store, unless delete_empty_campaign is true; never "all stores" by omission.
confirmedboolean, requiredMust be true.
delete_master_when_emptybooleanAlso remove the campaign when no store is left.
delete_empty_campaignbooleanRemove a campaign that has no store version left. Takes no channel_ids; refused while any store version remains.

export_discounts_v1

export_discounts_v1pim:read

The discount configuration as a CSV file (one row per store discount), with the list filters. Redeem codes are not included; extra codes are managed in Shopify.

ArgumentTypeDescription
search, method, family, shopify_status, publish_status, channel_idsAs for list_discounts_v1.