publ betaReference (MCP guide)
Open publ console

publ Reference

promotion_benefit_create

Add one ORDER_DISCOUNT or DISCOUNT benefit to an observed existing promotion campaign. Requires OWNER or MANAGE_PROMOTION and an observed Business-or-higher plan. Essential permits an initial campaign but does not permit this additional-benefit operation. The existing campaign may be inactive; adding a benefit does not activate it. Use the connected server's discovery to check availability; source implementation is not evidence that the running service has been updated.

  1. Read promotions_get and select an observed opaque pcid.
  2. Submit the complete benefit below with dryRun: true. Dates must fit within the selected campaign; supply your intended timezone as an offset or Z.
  3. Copy the returned creationRevision into expectedRevision, set dryRun: false, and submit the exact same values and stable requestId.
{
  "channelCode": "selected-channel-code",
  "pcid": "observed-campaign",
  "requestId": "add-order-benefit-001",
  "dryRun": true,
  "benefit": {
    "kind": "ORDER_DISCOUNT",
    "alias": "Seasonal offer",
    "memberDisplayText": "Order offer",
    "schedule": {"startAt": "2026-11-01T00:00:00+09:00", "endAt": "2026-11-30T23:59:59+09:00"},
    "target": {"kind": "ALL"},
    "discountAmount": "100",
    "benefitLimitOption": "ONE_TIME"
  }
}

The example dates and amount are illustrative. Use the selected campaign period and observed channel currency. KRW/JPY allow whole multiples of100 from100 to 10,000,000; USD allows0.01 to10,000 at cent precision. No conversion or rounding is performed. Alias uses4–20 UTF-16 units and display text1–14. Use UNLIMITED for unlimited application count. An unlimited period uses endAt: null only when the parent is unlimited. A segment target uses {"kind":"SEGMENT","distinctId":"observed-segment"} and must be freshly verified for the channel. There are no product-selection, trigger-override or activation fields for this bounded order-discount operation.

The plan reads the parent, existing benefits, plan, currency and audience twice. Saving rechecks them before one POST. The authoritative receipt supplies the new pbid; two parent/detail reads must agree and preserve existing settings and benefits. Source activation is retained without an additional activation call. Successful verification covers stored configuration, not visitor checkout or benefit delivery. This operation does not buy a service plan or transfer money.

If uncertain, retain the task ID and use task_status/task_resume with taskType: "promotion-benefit-create". Neither dispatches creation. Missing receipt identity requires inspecting the console; do not create again under a new ID or infer identity from a title/list difference. A prepared task needs the identical original call. Completed history is unconfirmed on replay; use a fresh promotions_get benefit detail for current values.

Open the one returned console link: the selected add-benefit screen for a current plan, or the exact new benefit detail after verified completion. Historical or uncertain results do not fabricate a destination. GRANT and LIMITED_TIME creation and unsupported product configuration use the source handoff where still unsupported. No benefit deletion or automatic restoration is promised.

Add a discount benefit with optional initial products

Confirm current connected discovery. Initial campaign creation still accepts only ORDER_DISCOUNT; this extension adds one benefit to an existing campaign.

The strict DISCOUNT object uses the common alias, memberDisplayText, schedule, target and required benefitLimitOption above, plus these fields. It has no benefit-level discountAmount, caller-supplied pbid, activation, trigger, repeatability, notice or automatic sales-stop controls. Source expression/execution triggers are EXPRESSION_VIEW and EXECUTION_PURCHASE. Explicit ONE_TIME or UNLIMITED controls the application limit; the source wizard's UNLIMITED default is not an omitted-input default. GRANT repeatability and LIMITED_TIME controls are separate contracts.

Field Contract
kind DISCOUNT.
productType SubscriptionProduct, ChannelActionProduct, PAppUnlockProduct, TicketEvent or CommerceProduct.
mode FIXED_PRICE for the three digital families; RATE_DISCOUNT or AMOUNT_DISCOUNT for TicketEvent/CommerceProduct.
products Required array of zero to100 unique {targetId,value} objects. Empty initial selection is permitted.
products[].targetId The observed choice.distinctId, not a numeric selector ID or existing relationship row ID.
products[].value Explicit plain decimal string, up to40 characters, in the selected mode. No sign, exponent, rounding, currency conversion or automatic price inference.
selection Required for a nonempty products array: exact page/limit/search from benefit-options plus its64-character lowercase hexadecimal optionsRevision. Omit for an empty selection unless intentionally binding an observed selector. If present, it must remain current even with no products.

For a nonempty selection, first call promotions_get benefit-options using only pcid, productType and selector query on the selected channel. The new benefit has no pbid yet. Choose only selectable rows from that exact page and retain their distinctId values. Preserve the query and optionsRevision in the create dry run. Review sourceWrite/sourceDependencies and copy the separately returned creationRevision to expectedRevision for actual submission with the same requestId and values. optionsRevision, connectionRevision, benefitRevision and creationRevision are not interchangeable. A dry run creates no journal or reserved campaign slot.

Values follow the connected-product discount rules: FIXED_PRICE is the final price bounded by the channel minimum and verified original selling price; RATE_DISCOUNT is a percentage, not a fractional ratio; AMOUNT_DISCOUNT is the reduction in observed channel currency. The channel-specific percentage exception and exact payment units still apply. A selectable choice does not prove its requested value is valid. Category/CommerceProductCategory mapping and fixed-price CP conversion remain unsupported. Products must already exist; this method does not create a product.

This empty initial selection needs no options read. Replace the channel, parent and dates with intended observed values:

{
  "channelCode": "selected-channel-code",
  "pcid": "observed-campaign",
  "requestId": "add-discount-empty-001",
  "dryRun": true,
  "benefit": {
    "kind": "DISCOUNT",
    "alias": "Member offer",
    "memberDisplayText": "Member price",
    "schedule": {"startAt": "2026-11-01T00:00:00+09:00", "endAt": "2026-11-30T23:59:59+09:00"},
    "target": {"kind": "ALL"},
    "benefitLimitOption": "UNLIMITED",
    "productType": "SubscriptionProduct",
    "mode": "FIXED_PRICE",
    "products": []
  }
}

This selected ticket example requires a fresh matching benefit-options read.

{
  "channelCode": "selected-channel-code",
  "pcid": "observed-campaign",
  "requestId": "add-ticket-discount-001",
  "dryRun": true,
  "benefit": {
    "kind": "DISCOUNT",
    "alias": "Ticket offer",
    "memberDisplayText": "Ticket offer",
    "schedule": {"startAt": "2026-11-01T00:00:00+09:00", "endAt": "2026-11-30T23:59:59+09:00"},
    "target": {"kind": "ALL"},
    "benefitLimitOption": "ONE_TIME",
    "productType": "TicketEvent",
    "mode": "RATE_DISCOUNT",
    "products": [{"targetId": "observed-ticket-event", "value": "10"}],
    "selection": {"page": 1, "limit": 15, "optionsRevision": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}
  }
}

Inputs

Field Required here Contract
pcid Yes string; pattern ^[A-Za-z0-9_-]{1,128}$
benefit Yes one of: ORDER_DISCOUNT, DISCOUNT, GRANT, LIMITED_TIME (by kind)
benefit.alias Yes When benefit.kind is ORDER_DISCOUNT: string; min length 4; max length 20
benefit.memberDisplayText Yes When benefit.kind is ORDER_DISCOUNT: string; min length 1; max length 14
benefit.schedule Yes When benefit.kind is ORDER_DISCOUNT: object
benefit.schedule.startAt Yes When benefit.kind is ORDER_DISCOUNT: string; pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$; format date-time
benefit.schedule.endAt Yes When benefit.kind is ORDER_DISCOUNT: string; pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$; format date-time or null
benefit.target Yes When benefit.kind is ORDER_DISCOUNT: one of: ALL, SEGMENT (by kind)
benefit.target.distinctId Yes When benefit.kind is ORDER_DISCOUNT and benefit.target.kind is SEGMENT: string; pattern ^[A-Za-z0-9_-]{1,128}$
benefit.discountAmount Yes When benefit.kind is ORDER_DISCOUNT: string; pattern ^(0|[1-9]\d{0,7})(\.\d{1,2})?$; Plain decimal amount in the freshly observed channel base currency. No currency conversion or rounding.
benefit.benefitLimitOption Yes When benefit.kind is ORDER_DISCOUNT: ONE_TIME, UNLIMITED
benefit.alias Yes When benefit.kind is DISCOUNT: string; min length 4; max length 20
benefit.memberDisplayText Yes When benefit.kind is DISCOUNT: string; min length 1; max length 14
benefit.schedule Yes When benefit.kind is DISCOUNT: object
benefit.schedule.startAt Yes When benefit.kind is DISCOUNT: string; pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$; format date-time
benefit.schedule.endAt Yes When benefit.kind is DISCOUNT: string; pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$; format date-time or null
benefit.target Yes When benefit.kind is DISCOUNT: one of: ALL, SEGMENT (by kind)
benefit.target.distinctId Yes When benefit.kind is DISCOUNT and benefit.target.kind is SEGMENT: string; pattern ^[A-Za-z0-9_-]{1,128}$
benefit.benefitLimitOption Yes When benefit.kind is DISCOUNT: ONE_TIME, UNLIMITED
benefit.productType Yes When benefit.kind is DISCOUNT: SubscriptionProduct, ChannelActionProduct, PAppUnlockProduct, TicketEvent, CommerceProduct
benefit.mode Yes When benefit.kind is DISCOUNT: FIXED_PRICE, RATE_DISCOUNT, AMOUNT_DISCOUNT
benefit.products Yes When benefit.kind is DISCOUNT: array; max items 100
benefit.products[].targetId Yes When benefit.kind is DISCOUNT: string; pattern ^[A-Za-z0-9_-]{1,128}$; targetId of a selectable choice from the options view.
benefit.products[].value Yes When benefit.kind is DISCOUNT: string; max length 40; pattern ^(0|[1-9]\d*)(\.\d+)?$; FIXED_PRICE (membership plans, content category products, paid-access products): the new sale price in the channel currency. RATE_DISCOUNT: the percentage. AMOUNT_DISCOUNT: the amount taken off.
benefit.alias Yes When benefit.kind is GRANT: string; min length 4; max length 20
benefit.schedule Yes When benefit.kind is GRANT: object
benefit.schedule.startAt Yes When benefit.kind is GRANT: string; pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$; format date-time
benefit.schedule.endAt Yes When benefit.kind is GRANT: string; pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$; format date-time or null
benefit.target Yes When benefit.kind is GRANT: one of: ALL, SEGMENT (by kind)
benefit.target.distinctId Yes When benefit.kind is GRANT and benefit.target.kind is SEGMENT: string; pattern ^[A-Za-z0-9_-]{1,128}$
benefit.executionTrigger No When benefit.kind is GRANT: EXECUTION_SIGNUP, EXECUTION_SIGNIN, EXECUTION_PURCHASE; default EXECUTION_SIGNUP
benefit.coupons No When benefit.kind is GRANT: array; max items 100; default []
benefit.coupons[].targetId Yes When benefit.kind is GRANT: string; pattern ^[A-Za-z0-9_-]{1,128}$
benefit.alias Yes When benefit.kind is LIMITED_TIME: string; min length 4; max length 20
benefit.schedule Yes When benefit.kind is LIMITED_TIME: object; Sales period. The end is always required.
benefit.schedule.startAt Yes When benefit.kind is LIMITED_TIME: string; pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$; format date-time
benefit.schedule.endAt Yes When benefit.kind is LIMITED_TIME: string; pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$; format date-time
benefit.target No When benefit.kind is LIMITED_TIME: object; default {"kind":"ALL"}
benefit.target.kind Yes When benefit.kind is LIMITED_TIME: ALL
benefit.noticeStartAt No When benefit.kind is LIMITED_TIME: string; pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$; format date-time
benefit.productType Yes When benefit.kind is LIMITED_TIME: SubscriptionProduct, ChannelActionProduct, PAppUnlockProduct
benefit.products No When benefit.kind is LIMITED_TIME: array; max items 100; default []
benefit.products[].targetId Yes When benefit.kind is LIMITED_TIME: string; pattern ^[A-Za-z0-9_-]{1,128}$
benefit.autoToggleOnBenefitPeriod No When benefit.kind is LIMITED_TIME: boolean; default true
confirmToken No string; pattern ^ct[a-f\d]{32}$; The confirmToken from this tool's preview result. Omit it to preview; repeat the same input with it to execute.