publ betaReference (MCP guide)
Open publ console

publ Reference

discount_settings_apply — create or configure an offer

Create or save a discount code or marketing coupon template in the selected channel. The existing-target contract comes first; the later creation extension is described below. One family and action select the business change; there are no separate tools for wizard steps. Read discounts_get with the same family and view.kind:profile, then copy its observed targetId and configurationRevision. This is separate from event-ticket discount policies, promotion campaigns and membership-product coupons.

See the workflow guide.

Access and input

This table describes existing-target profile/activation actions. Creation uses the separate draft, revision and task contract below.

Requires OWNER or DELEGATEE with MANAGE_DISCOUNTS. MANAGE_PROMOTION and creation-plan eligibility do not authorize or gate this existing-target edit. Hosted access is limited to the exact selected-channel resource; account and foreign-channel calls cannot apply or recover the task. Stored-task context is checked inside the workflow before credentials for another channel can be loaded.

Input Contract
channelCode Required; the reader's selected-channel rules.
family Required: discount-code or coupon-template.
targetId Required observed dcid or cotid, respectively; 1–128 ASCII letters, digits, underscores or hyphens. Reserved route names are rejected. Numeric row IDs, public codes, serials and titles are not this identity.
requestId Required; 8–80 ASCII letters, digits, underscores or hyphens. It becomes taskId. Preserve it with the original input for recovery.
expectedRevision Required 64 lowercase hexadecimal characters copied from the current profile's configurationRevision. Other views do not prepare a write.
action Required strict object: profile for either family, or activation for discount-code only.
dryRun Optional boolean, default false. A fresh true call validates and previews without a business write or saved task.

All objects reject unknown fields; null is not an omission. Existing-target edits accept no caller-supplied URL, raw body, segment, code, serial setting, usage limit, relative expiry or coupon activation.

Profile fields and omission

action field Families Rule
kind Both profile. At least one editable field below is required.
alias Both Administrative name, 2–20 UTF-16 units.
title Both Member-facing name, 2–20 UTF-16 units.
expiresAt Both Real ISO8601 whole-minute instant with explicit Z or offset; normalized to UTC. A changed instant must be future.
benefitDescription Coupon template 2–10 UTF-16 units.
description Coupon template Nonempty text, 1–52 UTF-16 units. Empty string and null cannot clear it.

Text is not trimmed. These lengths use UTF-16 units, so characters outside the basic multilingual plane count as two. Omitted editable fields preserve the observed values. Saving a profile composes the entire supported source form, so an invalid stored name or benefit text may require an explicit valid replacement even when the intended change is another field.

Omitted expiry preserves its stored instant, including seconds or a past date. A supplied different expiry must be future at preparation and again before dispatch. This bridge rule is stricter than the original date picker's browser-local calendar-day minimum; no local timezone is inferred. Stored null or malformed absolute expiry requires an explicit valid replacement for profile editing. Null cannot remove expiry.

Discount-code editing requires the first observed connected segment and sends its distinctId unchanged. Missing selection blocks editing. Coupon editing preserves its usageConditionSegmentId, omitting the source body field when the stored value is empty. The source segment-change controls are disabled; neither flow reassigns segments. An omitted coupon description preserves null or empty text by omitting that source field and then checking it remains unchanged. Source omission does not prove explicit clearing, so the writer rejects an empty requested description.

The original illustrative example is retained below. Its placeholder revision is not valid input until replaced with the returned configurationRevision; replace every illustrative identity and choose the intended future expiry.

{
  "channelCode": "selected-channel",
  "family": "coupon-template",
  "targetId": "observed-template",
  "requestId": "coupon-settings-001",
  "expectedRevision": "COPY_CONFIGURATION_REVISION",
  "action": {
    "kind": "profile",
    "title": "Member offer",
    "benefitDescription": "Summer",
    "expiresAt": "2030-12-01T23:59:00+09:00"
  }
}

Complete input examples

The 64-character revisions below are schema-shaped placeholders, not server-issued revisions. Read the exact profile first and replace them. These examples validate input shapes only and do not authorize live offer changes.

Change an existing discount code's administrative and display names:

{
  "channelCode": "selected-channel",
  "family": "discount-code",
  "targetId": "observed-discount",
  "requestId": "discount-settings-001",
  "expectedRevision": "1111111111111111111111111111111111111111111111111111111111111111",
  "action": {
    "kind": "profile",
    "alias": "Summer code",
    "title": "Summer offer"
  }
}

Preview a new absolute expiry while preserving other fields:

{
  "channelCode": "selected-channel",
  "family": "discount-code",
  "targetId": "observed-discount",
  "requestId": "discount-expiry-001",
  "expectedRevision": "1111111111111111111111111111111111111111111111111111111111111111",
  "action": {
    "kind": "profile",
    "expiresAt": "2030-12-01T23:59:00+09:00"
  },
  "dryRun": true
}

Change a coupon template's display text:

{
  "channelCode": "selected-channel",
  "family": "coupon-template",
  "targetId": "observed-template",
  "requestId": "coupon-profile-001",
  "expectedRevision": "1111111111111111111111111111111111111111111111111111111111111111",
  "action": {
    "kind": "profile",
    "title": "Member offer",
    "benefitDescription": "Summer",
    "description": "A summer offer for eligible members."
  }
}

Activate or deactivate one discount code

Only discount-code accepts action.kind:activation with required boolean active. It selects exactly one observed code, even though the source endpoint has a bulk name. Coupon activation and batch activation are outside this method. A matching active value is a no-op.

Activate:

{
  "channelCode": "selected-channel",
  "family": "discount-code",
  "targetId": "observed-discount",
  "requestId": "discount-active-001",
  "expectedRevision": "1111111111111111111111111111111111111111111111111111111111111111",
  "action": {
    "kind": "activation",
    "active": true
  }
}

Deactivate:

{
  "channelCode": "selected-channel",
  "family": "discount-code",
  "targetId": "observed-discount",
  "requestId": "discount-inactive-001",
  "expectedRevision": "1111111111111111111111111111111111111111111111111111111111111111",
  "action": {
    "kind": "activation",
    "active": false
  }
}

Save and verification

The revision binds family, complete projected target, ordered connected segments and selected channel/operator/credential context. The writer rereads the target twice and checks current context, then rechecks a prepared task immediately before dispatch. A mismatch returns a conflict; it does not silently rebase the change. These repeated observations are not an atomic compare-and-swap or a lock against console writers.

Profile changes send one PATCH to /seller/api/v1/discount-codes/{targetId} or /seller/api/v1/coupon-templates/{targetId} with the composed wizard fields. Activation sends one POST to the discount-code /bulk-activate or /bulk-deactivate path with exactly one dcid and isActivated. The shared transport requires HTTP 200 with a data envelope, no caller query, the selected channel header and its verified credentials.

A profile receipt must identify the exact selected family/target and match the requested profile plus preserved projected fields. An activation response alone cannot confirm completion. Two fresh profile observations and final context checks must match the intended result. Comparison preserves every projected field, ordered segment and untouched setting except updatedAt; equivalent expiry instants are normalized. Unknown source fields are not projected, so this is not full raw-DTO preservation or verification of an unread benefit graph.

Result Meaning and next step
DISCOUNT_SETTINGS_PLAN Fresh dry run: target, sourceWrite, changesRequired and writesPerformed:false; verification.confirmed:false. No task is persisted.
DISCOUNT_SETTINGS_COMPLETE Current success after verification, or a verified no-op: phase done, target, configurationRevision and noop. Check historical and verification.confirmed before treating it as current.
Pending/error with phase sent A save may have happened. Preserve the task and original input; inspect the error and journalPersistence when returned. Reconcile by reading, never by another mutation.
DISCOUNT_CONFLICT / DISCOUNT_CHANGED Revision or repeated observations changed. Read the profile again; preserve any already-sent task before preparing unrelated new work.
DISCOUNT_EXPIRY_UNVERIFIED / DISCOUNT_EXPIRY_IN_PAST / DISCOUNT_SEGMENT_UNVERIFIED Required source-form state or a requested expiry is invalid. Correct the intended editable input or inspect the original target.
DISCOUNT_RECEIPT_MISMATCH / DISCOUNT_READBACK_MISMATCH Saved response or fresh values cannot confirm the intended change and preservation. A sent task stays uncertain.
REQUEST_ID_CONFLICT / TASK_STATE_UNVERIFIED Original request identity or saved journal integrity differs. Do not edit the record or change requestId to bypass it.
RESOURCE_SCOPE_MISMATCH / DISCOUNT_CONTEXT_CHANGED Wrong selected resource or changed connection/operator/permission context. Retain the original target and recover its valid context.

Fresh real no-ops persist a done task but send no write. On normal task results, writesPerformed is false for no-op/prepared work, true for an acknowledged save, and null for an unacknowledged sent attempt; it is not proof of completion or a per-call mutation count. Error payloads can omit it. verification distinguishes current confirmation, storedCompletion, atomicSnapshot:false, visitorBenefitVerified:false and financialActionPerformed:false.

Saved work and recovery

Use task_status and task_resume with taskType discount-settings and the original taskId. The durable phases are prepared, sent and done. The sent marker must persist before dispatch; loss of a response, partial application, receipt mismatch or a later guard failure never resets it to prepared or causes automatic resend.

Status checks the saved record and current context, without a fresh profile read or business write. Resume only observes: prepared work requires the identical original apply input after fresh checks; sent work rereads the known selected target and can complete only if the intended state and preserved fields match. No creation identity needs guessing because the target existed before the request. A current matching read can reconcile a lost receipt without establishing that this client caused the change.

Keep the original expectedRevision, family, target, action and requestId. Changing dryRun does not change the request fingerprint. A dry run against an existing identical task returns a historical saved plan, not a new current preview. Completed apply replay, status and completed resume are historical with verification.confirmed:false and no current profile link or configurationRevision. Read discounts_get again for current state. Credential refresh may be reconciled for sent work when the remaining context still matches; prepared dispatch retains its original credential binding.

There is no automatic rollback. A reverse edit needs a fresh profile revision and a new intentional request after resolving the prior task. Exact raw restoration is limited: updatedAt is not restored, an earlier null expiry cannot be written, empty descriptions cannot be explicitly cleared, and a changed expiry cannot restore a past instant. Restoring one configured value does not undo visitor effects.

Console destination and remaining scope

Fresh plans and confirmed current saves/no-ops return the exact selected profile URL under /channels/{channelCode}/discounts/discount-codes/{targetId} or /channels/{channelCode}/discounts/coupon-templates/{targetId}. Follow the validated returned address. It does not open or prefill the edit wizard. Pending/error results and historical replay do not provide a current verified destination; demo omits live URLs.

Use discount_handoff for coupon issuance or withdrawal, or an optional visit to the original create/edit screen. Creation through this writer is described below. Settlement, billing, payments and financial execution remain human-console actions. The existing-target actions do not create offers, batch-activate codes, issue/withdraw coupons, reassign segments, clear descriptions, redeem codes, change plans or prove visitor eligibility/checkout.

Create a discount code or coupon template

It supersedes the earlier creation-handoff-only boundary for this exact contract. Existing profile/activation actions and discount-settings journals remain unchanged. Creation uses the separate internal discount-create task namespace; no new public method is registered.

Require channelCode, family, requestId and expectedRevision from discounts_get view:create with the same draft. Do not provide targetId. requestId is 8–80 ASCII letters, digits, underscores or hyphens; expectedRevision is 64 lowercase hexadecimal characters. dryRun defaults to false. OWNER or DELEGATEE with MANAGE_DISCOUNTS and the exact selected-channel resource are required, plus the creation plan/capacity checks in the getter.

draft field Families Contract
alias Both Required administrative name, 2–20 UTF-16 units.
title Both Required member-facing name, 2–20 UTF-16 units.
expiresAt Both Required future whole-minute ISO8601 instant with explicit timezone, normalized to UTC without changing the instant.
usageConditionSegmentId Both Optional observed distinctId of an existing selected-channel segment: 1–128 ASCII letters, digits, underscores or hyphens, with reserved route names rejected. Prepare it separately; do not pass a segment body or null.
code Discount code Required 4–16 uppercase ASCII letters, digits or hyphens; the reserved CPN prefix is rejected.
benefitDescription Coupon template Required 2–10 UTF-16 units.
description Coupon template Optional 0–52 UTF-16 units. Empty text is omitted from the creation request.

Text is preserved without trimming. Expiry is intentionally stricter than the original nonempty browser-local date input; no locale or timezone is guessed. The reachable coupon creation flow uses RANDOM serial generation. KEYWORD, serial keywords, relative expiry, minimum purchase/amount and usage limits are not accepted. Do not send a serial-generation selector or isActivated: creation always submits isActivated:true. Omitted segment and empty description are omitted from the source body; server-generated defaults are observed rather than invented. This configures a template without issuing any coupons or creating its optional promotion step.

A fresh dry run repeats preparation and duplicate validation where applicable, returning DISCOUNT_CREATE_PLAN without a saved task or creation POST. Actual creation rechecks the stable inventory, plan, selected segment, expiry and creationRevision, persists prepared and then sent progress, and sends one POST to /seller/api/v1/discount-codes or /seller/api/v1/coupon-templates using the verified selected-channel credentials/header. Duplicate-code POST is a separate validation call, not an additional offer creation.

Creation receipt and verification

The shared transport accepts HTTP200/201 as candidate acknowledgements with a data envelope. A complete authoritative receipt must supply the new dcid/cotid and numeric identity, belong to the selected family/channel and not reuse an existing identity. Preserve it durably before follow-up reads. No ID can be supplied by the caller or inferred from a matching code, name or inventory difference.

Two fresh observations must agree on that exact detail and the complete family inventory. The new projected record must match the requested values and receipt, while existing offers, current plan and the optional segment's conditions remain unchanged. The new target's equivalent expiry instants are normalized and updatedAt is excluded from receipt/detail equality. Existing inventory/segment observations remain part of preservation. Unknown private DTO fields are not projected, so this is not a complete raw-record backup or verification of the benefit graph.

DISCOUNT_CREATED returns phase:done, targetId, target and current configurationRevision only after confirmation. Its verification separates confirmed/storedCompletion from atomicSnapshot:false, financialActionPerformed:false and visitorBenefitVerified:false. The fresh confirmed link opens the exact created profile; the plan opens /create. Pending/error and historical outcomes have no current verified link. These destinations do not submit a wizard, certify eligibility, deliver coupons or redeem benefits.

Creation recovery and cleanup limits

Retain the original input, requestId and taskType:discount-create. Status reports stored progress with current context checks and no business write; resume never dispatches creation. An untouched prepared task can proceed only through the identical original apply after fresh checks. Once sent, exact apply retries and resume observe only and never repeat POST. A different requestId is not a recovery strategy for unknown creation; no server idempotency key, atomic capacity/uniqueness reservation or global new-request lock is promised.

DISCOUNT_CREATION_ID_UNKNOWN means no authoritative receipt was saved. Keep the task and inspect the original console; do not adopt any matching row or recreate it. With a saved receipt, read loss may reconcile against its exact identity. DISCOUNT_CREATE_RECEIPT_MISMATCH, DISCOUNT_CREATE_READBACK_MISMATCH, sibling/segment/plan drift or journalPersistence.saved:false cannot establish success. DISCOUNT_CREATE_CONFLICT requires fresh preparation before an unsent operation; REQUEST_ID_CONFLICT and TASK_STATE_UNVERIFIED must not be bypassed by editing stored records.

Task context remains bound to channel, connection, operator and permissions across shared file stores. Credential refresh is tolerated only after the prepared phase while the remaining context matches. Completed apply replay, status and completed resume are historical, with verification.confirmed:false and no current configurationRevision/link.

There is no offer deletion or automatic cleanup/rollback in this contract or the original creation screens. Deactivation is not deletion; creating an equivalent offer cannot restore identity or remove an earlier one. Any authorized actual creation test needs dedicated dev data and an explicit cleanup or retention outcome. Issuance, withdrawal, payments and promotion creation retain their separate flows.

Illustrative preview using the same prepared discount-code draft. Replace every identity, the future expiry and all-zero creation revision with the matching current values:

{
  "channelCode": "selected-channel",
  "family": "discount-code",
  "requestId": "discount-create-001",
  "expectedRevision": "0000000000000000000000000000000000000000000000000000000000000000",
  "dryRun": true,
  "action": {
    "kind": "create",
    "draft": {
      "alias": "Summer code",
      "title": "Summer offer",
      "code": "SUMMER-2030",
      "expiresAt": "2030-12-01T23:59:00+09:00",
      "usageConditionSegmentId": "observed-segment"
    }
  }
}

Preview a RANDOM coupon template without a selected segment:

{
  "channelCode": "selected-channel",
  "family": "coupon-template",
  "requestId": "coupon-template-create-001",
  "expectedRevision": "0000000000000000000000000000000000000000000000000000000000000000",
  "dryRun": true,
  "action": {
    "kind": "create",
    "draft": {
      "alias": "Summer template",
      "title": "Summer offer",
      "benefitDescription": "Summer",
      "description": "",
      "expiresAt": "2030-12-01T23:59:00+09:00"
    }
  }
}

Inputs

Field Required here Contract
family Yes When alternative 1: one of: discount-code, coupon-template
targetId Yes When alternative 1 and family is discount-code: string; pattern ^[A-Za-z0-9_-]{1,128}$
action Yes When alternative 1 and family is discount-code: one of: profile, activation (by kind)
action.alias No When alternative 1 and family is discount-code and action.kind is profile: string; min length 2; max length 20
action.title No When alternative 1 and family is discount-code and action.kind is profile: string; min length 2; max length 20
action.expiresAt No When alternative 1 and family is discount-code and action.kind is profile: 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
action.active Yes When alternative 1 and family is discount-code and action.kind is activation: boolean
confirmToken No When alternative 1 and family is discount-code: 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.
targetId Yes When alternative 1 and family is coupon-template: string; pattern ^[A-Za-z0-9_-]{1,128}$
action Yes When alternative 1 and family is coupon-template: object
action.kind Yes When alternative 1 and family is coupon-template: profile
action.alias No When alternative 1 and family is coupon-template: string; min length 2; max length 20
action.title No When alternative 1 and family is coupon-template: string; min length 2; max length 20
action.expiresAt No When alternative 1 and family is coupon-template: 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
action.benefitDescription No When alternative 1 and family is coupon-template: string; min length 2; max length 10
action.description No When alternative 1 and family is coupon-template: string; min length 1; max length 52
confirmToken No When alternative 1 and family is coupon-template: 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.
family Yes When alternative 2: one of: discount-code, coupon-template
action Yes When alternative 2 and family is discount-code: object
action.kind Yes When alternative 2 and family is discount-code: create
action.draft Yes When alternative 2 and family is discount-code: object
action.draft.alias Yes When alternative 2 and family is discount-code: string; min length 2; max length 20
action.draft.title Yes When alternative 2 and family is discount-code: string; min length 2; max length 20
action.draft.expiresAt Yes When alternative 2 and family is discount-code: 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
action.draft.usageConditionSegmentId No When alternative 2 and family is discount-code: string; pattern ^[A-Za-z0-9_-]{1,128}$
action.draft.code Yes When alternative 2 and family is discount-code: string; min length 4; max length 16; pattern ^[A-Z0-9-]+$
confirmToken No When alternative 2 and family is discount-code: 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.
action Yes When alternative 2 and family is coupon-template: object
action.kind Yes When alternative 2 and family is coupon-template: create
action.draft Yes When alternative 2 and family is coupon-template: object
action.draft.alias Yes When alternative 2 and family is coupon-template: string; min length 2; max length 20
action.draft.title Yes When alternative 2 and family is coupon-template: string; min length 2; max length 20
action.draft.expiresAt Yes When alternative 2 and family is coupon-template: 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
action.draft.usageConditionSegmentId No When alternative 2 and family is coupon-template: string; pattern ^[A-Za-z0-9_-]{1,128}$
action.draft.benefitDescription Yes When alternative 2 and family is coupon-template: string; min length 2; max length 10
action.draft.description No When alternative 2 and family is coupon-template: string; max length 52
confirmToken No When alternative 2 and family is coupon-template: 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.