publ betaReference (MCP guide)
Open publ console

commerce_creation_get

# commerce_creation_get

Prepare a complete X00004 product draft and return its creation revision. This read creates no product, uploads no image and reserves no slug.

Connected source: Only X00004 is exposed here; legacy shops and ticket events in the owner module are not connected. The source registry has 153 operations while the older recorded runtime has 145. Follow the [common shop connection](../guides/commerce-products.md).

Existing drafts without these fields retain their prior contract.

## Complete draft input

Require channelCode, pAppCode:X00004 and draft. No requestId, expectedRevision or dryRun is accepted by this preparation read. Supply completed [commerce_image_upload](commerce_image_upload.md) task IDs bound to the same operator/connection/credential version, installation, purpose and configured storage.

| draft field | Requirement or default |
| --- | --- |
| name | Required, trimmed 2–50 UTF-16 units. |
| oneLiner | Empty or trimmed 2–100; defaults empty. |
| slug | Required string, at most 150. May be empty; supports the source Korean, Latin, Japanese and CJK ranges, whitespace and hyphens. This is not a uniqueness reservation. |
| price | Required nonnegative decimal string, up to ten integer digits and two decimal places, then validated against the observed KRW/USD rules below. |
| originalPrice | Decimal string or null; defaults null and is sent as zero/no original price. Explicit non-null values must meet price rules. |
| imageTaskIds | 1–10 distinct completed product-image task IDs, in desired image order. |
| description | String up to 50000; defaults empty. No visual rich-editor or rendering validation. |
| returnPolicyContent | Required string, 1–50000. |
| shippingPolicyId | Required observed existing same-store business ID. This does not create/edit the policy. |
| categoryIds / labelIds / badgeIds | Each at most five distinct observed existing same-store IDs; default empty arrays. |
| saleStatus | Required ACTIVE or DISCONTINUED. |
| visibilityStatus | Required VISIBLE or DISABLED. |
| options | Required single or combined structure described below. |
| orderQuantityLimit | Integer 1–9999 or null; default null disables the limit. |
| enableReviewFeature / enableQuestionFeature | Booleans, each defaults false. |
| searchIndexable | Boolean, defaults true. |

Existing association IDs and option keys accept 1–160 ASCII letters, digits, underscores or hyphens. Image task IDs instead use the 8–80-character request-ID rule. IDs must come from observed records; titles and numeric row IDs are not replacements.

Base and non-null original prices follow the [existing product price rules](commerce_product_settings_apply.md): KRW 100–9,999,999,990 in multiples of 10; USD 1.00–9,999,999.00 in 0.01 steps. Base price may equal but not exceed a supplied original price. There is no currency override or conversion. These are source configuration constraints, not a completed checkout or billing calculation.

## Options and initial stock

For options.kind:single, supply quantity (integer 0–99,999,999) and optional sku (default empty). The source builds one Default/standard option and one ACTIVE tracked-inventory variant with zero additional price. Product saleStatus is separate from that variant status.

For options.kind:combined, supply 1–3 groups and 1–300 variants. Each group has a unique key, a trimmed title of 1–25 units and 1–300 values with globally unique keys and trimmed names of 1–50 units. The product of the group value counts must not exceed 300. Each variant supplies quantity, explicit ACTIVE/DISCONTINUED saleStatus and values selecting exactly one key per group in group order. Combinations must be distinct and every declared value must be used; the schema does not require every possible combination.

Both forms accept sku up to 100 ASCII letters, digits or hyphens, including empty. Combined variants additionally accept a signed decimal-string additionalPrice, default "0". Its magnitude and base-plus-additional total must stay within the currency maximum; the total may be zero, and KRW adjustments use multiples of 10. Every new variant tracks inventory. No per-variant image, access controls or scheduled sale period is exposed. [Initial buyer input and add-ons](#initial-buyer-input-and-add-ons) are part of the complete creation draft; omitting them retains the earlier empty arrays. Common connection for these initial options is separately scoped below.

## Preparation output and next step

COMMERCE_CREATION_READY includes revision, the source-shaped request, resolved images and dependency records, with writesPerformed:false. The workflow reads the draft's image/dependency snapshot twice and checks current context. Shipping/category/label/badge records must belong to the existing store and not be purged/archived.

Copy **revision into commerce_create.expectedRevision** and submit the same complete draft. This is not creationRevision and not a revision from an existing-product reader. Changing any draft value, image binding or linked dependency requires a new preparation read. A valid revision does not reserve backend state or exclude concurrent console changes.

A verified preparation points to the selected shop's products/create screen. It is not a save.

## Inputs

| Field | Required here | Contract |
| --- | --- | --- |
| `pAppCode` | Yes | one of: `X00004`, `E00003` |
| `draft` | Yes | When `pAppCode` is `X00004`: object |
| `draft.name` | Yes | When `pAppCode` is `X00004`: string; min length 2; max length 50 |
| `draft.oneLiner` | No | When `pAppCode` is `X00004`: `` or string; min length 2; max length 100; default `` |
| `draft.slug` | Yes | When `pAppCode` is `X00004`: string; max length 150; pattern `^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z0-9\s\-\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF]*$` |
| `draft.price` | Yes | When `pAppCode` is `X00004`: string; pattern `^(0\|[1-9]\d{0,9})(\.\d{1,2})?$` |
| `draft.originalPrice` | No | When `pAppCode` is `X00004`: string; pattern `^(0\|[1-9]\d{0,9})(\.\d{1,2})?$` or null; default `null` |
| `draft.imageTaskIds` | Yes | When `pAppCode` is `X00004`: array; items: string; pattern `^[A-Za-z0-9_-]{8,80}$`; Reuse this requestId and the exact original input after interruption. Never change requestId to retry an uncertain write.; min items 1; max items 10 |
| `draft.description` | No | When `pAppCode` is `X00004`: string; max length 50000; default `` |
| `draft.returnPolicyContent` | Yes | When `pAppCode` is `X00004`: string; min length 1; max length 50000 |
| `draft.shippingPolicyId` | Yes | When `pAppCode` is `X00004`: string; min length 1; max length 160; pattern `^[A-Za-z0-9_-]+$`; Exact resource identifier returned by this operation, never a title, unrelated row ID or URL. |
| `draft.categoryIds` | No | When `pAppCode` is `X00004`: array; items: string; min length 1; max length 160; pattern `^[A-Za-z0-9_-]+$`; Exact resource identifier returned by this operation, never a title, unrelated row ID or URL.; max items 5; default `[]` |
| `draft.labelIds` | No | When `pAppCode` is `X00004`: array; items: string; min length 1; max length 160; pattern `^[A-Za-z0-9_-]+$`; Exact resource identifier returned by this operation, never a title, unrelated row ID or URL.; max items 5; default `[]` |
| `draft.badgeIds` | No | When `pAppCode` is `X00004`: array; items: string; min length 1; max length 160; pattern `^[A-Za-z0-9_-]+$`; Exact resource identifier returned by this operation, never a title, unrelated row ID or URL.; max items 5; default `[]` |
| `draft.saleStatus` | Yes | When `pAppCode` is `X00004`: `ACTIVE`, `DISCONTINUED` |
| `draft.visibilityStatus` | Yes | When `pAppCode` is `X00004`: `VISIBLE`, `DISABLED` |
| `draft.options` | Yes | When `pAppCode` is `X00004`: one of: `single`, `combined` (by `kind`) |
| `draft.options.sku` | No | When `pAppCode` is `X00004` and `draft.options.kind` is `single`: string; max length 100; pattern `^[a-zA-Z0-9-]*$`; default `` |
| `draft.options.quantity` | Yes | When `pAppCode` is `X00004` and `draft.options.kind` is `single`: integer; minimum 0; maximum 99999999 |
| `draft.options.groups` | Yes | When `pAppCode` is `X00004` and `draft.options.kind` is `combined`: array; min items 1; max items 3 |
| `draft.options.groups[].key` | Yes | When `pAppCode` is `X00004` and `draft.options.kind` is `combined`: string; min length 1; max length 160; pattern `^[A-Za-z0-9_-]+$`; Exact resource identifier returned by this operation, never a title, unrelated row ID or URL. |
| `draft.options.groups[].title` | Yes | When `pAppCode` is `X00004` and `draft.options.kind` is `combined`: string; min length 1; max length 25 |
| `draft.options.groups[].values` | Yes | When `pAppCode` is `X00004` and `draft.options.kind` is `combined`: array; min items 1; max items 300 |
| `draft.options.groups[].values[].key` | Yes | When `pAppCode` is `X00004` and `draft.options.kind` is `combined`: string; min length 1; max length 160; pattern `^[A-Za-z0-9_-]+$`; Exact resource identifier returned by this operation, never a title, unrelated row ID or URL. |
| `draft.options.groups[].values[].name` | Yes | When `pAppCode` is `X00004` and `draft.options.kind` is `combined`: string; min length 1; max length 50 |
| `draft.options.variants` | Yes | When `pAppCode` is `X00004` and `draft.options.kind` is `combined`: array; min items 1; max items 300 |
| `draft.options.variants[].sku` | No | When `pAppCode` is `X00004` and `draft.options.kind` is `combined`: string; max length 100; pattern `^[a-zA-Z0-9-]*$`; default `` |
| `draft.options.variants[].quantity` | Yes | When `pAppCode` is `X00004` and `draft.options.kind` is `combined`: integer; minimum 0; maximum 99999999 |
| `draft.options.variants[].additionalPrice` | No | When `pAppCode` is `X00004` and `draft.options.kind` is `combined`: string; pattern `^-?(0\|[1-9]\d{0,9})(\.\d{1,2})?$`; default `0` |
| `draft.options.variants[].saleStatus` | Yes | When `pAppCode` is `X00004` and `draft.options.kind` is `combined`: `ACTIVE`, `DISCONTINUED` |
| `draft.options.variants[].values` | Yes | When `pAppCode` is `X00004` and `draft.options.kind` is `combined`: array; items: string; min length 1; max length 160; pattern `^[A-Za-z0-9_-]+$`; Exact resource identifier returned by this operation, never a title, unrelated row ID or URL.; min items 1; max items 3 |
| `draft.orderQuantityLimit` | No | When `pAppCode` is `X00004`: integer; minimum 1; maximum 9999 or null; default `null` |
| `draft.enableReviewFeature` | No | When `pAppCode` is `X00004`: boolean; default `false` |
| `draft.enableQuestionFeature` | No | When `pAppCode` is `X00004`: boolean; default `false` |
| `draft.searchIndexable` | No | When `pAppCode` is `X00004`: boolean; default `true` |
| `draft.seoTitle` | No | When `pAppCode` is `X00004`: string; max length 100 |
| `draft.seoDescription` | No | When `pAppCode` is `X00004`: string; max length 5000 |
| `draft.seoKeywords` | No | When `pAppCode` is `X00004`: array; items: string; min length 1 |
| `draft.seoImgAltText` | No | When `pAppCode` is `X00004`: string; max length 300 |
| `draft.inputOption` | No | When `pAppCode` is `X00004`: object |
| `draft.inputOption.title` | Yes | When `pAppCode` is `X00004`: string; min length 1; max length 50 |
| `draft.inputOption.placeholder` | Yes | When `pAppCode` is `X00004`: string; min length 1; max length 50 |
| `draft.addons` | No | When `pAppCode` is `X00004`: object |
| `draft.addons.title` | Yes | When `pAppCode` is `X00004`: string; min length 1; max length 50 |
| `draft.addons.items` | Yes | When `pAppCode` is `X00004`: array; min items 1; max items 3 |
| `draft.addons.items[].name` | Yes | When `pAppCode` is `X00004`: string; min length 1; max length 50 |
| `draft.addons.items[].additionalPrice` | Yes | When `pAppCode` is `X00004`: string; pattern `^(0\|[1-9]\d{0,9})(\.\d{1,2})?$` |
| `draft.addons.items[].saleStatus` | Yes | When `pAppCode` is `X00004`: `ACTIVE`, `DISCONTINUED` |
| `channelCode` | Yes | When `pAppCode` is `X00004`: string; min length 1; max length 512; The exact channelCode selected through channel discovery. Do not supply a URL, channel numeric ID, account ID or credentials. |
| `draft` | Yes | When `pAppCode` is `E00003`: object |
| `draft.title` | Yes | When `pAppCode` is `E00003`: string; min length 1; max length 80 |
| `draft.summary` | No | When `pAppCode` is `E00003`: string; max length 200; default `` |
| `draft.description` | Yes | When `pAppCode` is `E00003`: string; min length 1; max length 20000 |
| `draft.noticeGuidelines` | Yes | When `pAppCode` is `E00003`: string; min length 1; max length 20000 |
| `draft.startDate` | Yes | When `pAppCode` is `E00003`: string; pattern `^\d{4}-\d{2}-\d{2}$` |
| `draft.endDate` | Yes | When `pAppCode` is `E00003`: string; pattern `^\d{4}-\d{2}-\d{2}$` |
| `draft.ageRated` | No | When `pAppCode` is `E00003`: string; max length 100; default `` |
| `draft.imageTaskId` | Yes | When `pAppCode` is `E00003`: string; pattern `^[A-Za-z0-9_-]{8,80}$`; Reuse this requestId and the exact original input after interruption. Never change requestId to retry an uncertain write. |
| `draft.translation` | No | When `pAppCode` is `E00003`: object |
| `draft.translation.title` | No | When `pAppCode` is `E00003`: object |
| `draft.translation.title.ko` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.title.en` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.title.ja` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.title.zh` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.title.zh-Hant` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.title.fr` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.title.es` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.title.vi` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.title.ru` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.title.it` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.summary` | No | When `pAppCode` is `E00003`: object |
| `draft.translation.summary.ko` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.summary.en` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.summary.ja` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.summary.zh` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.summary.zh-Hant` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.summary.fr` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.summary.es` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.summary.vi` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.summary.ru` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.summary.it` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.description` | No | When `pAppCode` is `E00003`: object |
| `draft.translation.description.ko` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.description.en` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.description.ja` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.description.zh` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.description.zh-Hant` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.description.fr` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.description.es` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.description.vi` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.description.ru` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.description.it` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.ageRated` | No | When `pAppCode` is `E00003`: object |
| `draft.translation.ageRated.ko` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.ageRated.en` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.ageRated.ja` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.ageRated.zh` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.ageRated.zh-Hant` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.ageRated.fr` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.ageRated.es` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.ageRated.vi` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.ageRated.ru` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.ageRated.it` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.noticeGuidelines` | No | When `pAppCode` is `E00003`: object |
| `draft.translation.noticeGuidelines.ko` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.noticeGuidelines.en` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.noticeGuidelines.ja` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.noticeGuidelines.zh` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.noticeGuidelines.zh-Hant` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.noticeGuidelines.fr` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.noticeGuidelines.es` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.noticeGuidelines.vi` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.noticeGuidelines.ru` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.noticeGuidelines.it` | No | When `pAppCode` is `E00003`: string |
| `draft.translation.thumbnailSrc` | No | When `pAppCode` is `E00003`: object |
| `draft.translation.thumbnailSrc.ko` | No | When `pAppCode` is `E00003`: object or `` |
| `draft.translation.thumbnailSrc.ko.imageTaskId` | Yes | When `pAppCode` is `E00003`: string; pattern `^[A-Za-z0-9_-]{8,80}$`; Reuse this requestId and the exact original input after interruption. Never change requestId to retry an uncertain write. |
| `draft.translation.thumbnailSrc.en` | No | When `pAppCode` is `E00003`: object or `` |
| `draft.translation.thumbnailSrc.en.imageTaskId` | Yes | When `pAppCode` is `E00003`: string; pattern `^[A-Za-z0-9_-]{8,80}$`; Reuse this requestId and the exact original input after interruption. Never change requestId to retry an uncertain write. |
| `draft.translation.thumbnailSrc.ja` | No | When `pAppCode` is `E00003`: object or `` |
| `draft.translation.thumbnailSrc.ja.imageTaskId` | Yes | When `pAppCode` is `E00003`: string; pattern `^[A-Za-z0-9_-]{8,80}$`; Reuse this requestId and the exact original input after interruption. Never change requestId to retry an uncertain write. |
| `draft.translation.thumbnailSrc.zh` | No | When `pAppCode` is `E00003`: object or `` |
| `draft.translation.thumbnailSrc.zh.imageTaskId` | Yes | When `pAppCode` is `E00003`: string; pattern `^[A-Za-z0-9_-]{8,80}$`; Reuse this requestId and the exact original input after interruption. Never change requestId to retry an uncertain write. |
| `draft.translation.thumbnailSrc.zh-Hant` | No | When `pAppCode` is `E00003`: object or `` |
| `draft.translation.thumbnailSrc.zh-Hant.imageTaskId` | Yes | When `pAppCode` is `E00003`: string; pattern `^[A-Za-z0-9_-]{8,80}$`; Reuse this requestId and the exact original input after interruption. Never change requestId to retry an uncertain write. |
| `draft.translation.thumbnailSrc.fr` | No | When `pAppCode` is `E00003`: object or `` |
| `draft.translation.thumbnailSrc.fr.imageTaskId` | Yes | When `pAppCode` is `E00003`: string; pattern `^[A-Za-z0-9_-]{8,80}$`; Reuse this requestId and the exact original input after interruption. Never change requestId to retry an uncertain write. |
| `draft.translation.thumbnailSrc.es` | No | When `pAppCode` is `E00003`: object or `` |
| `draft.translation.thumbnailSrc.es.imageTaskId` | Yes | When `pAppCode` is `E00003`: string; pattern `^[A-Za-z0-9_-]{8,80}$`; Reuse this requestId and the exact original input after interruption. Never change requestId to retry an uncertain write. |
| `draft.translation.thumbnailSrc.vi` | No | When `pAppCode` is `E00003`: object or `` |
| `draft.translation.thumbnailSrc.vi.imageTaskId` | Yes | When `pAppCode` is `E00003`: string; pattern `^[A-Za-z0-9_-]{8,80}$`; Reuse this requestId and the exact original input after interruption. Never change requestId to retry an uncertain write. |
| `draft.translation.thumbnailSrc.ru` | No | When `pAppCode` is `E00003`: object or `` |
| `draft.translation.thumbnailSrc.ru.imageTaskId` | Yes | When `pAppCode` is `E00003`: string; pattern `^[A-Za-z0-9_-]{8,80}$`; Reuse this requestId and the exact original input after interruption. Never change requestId to retry an uncertain write. |
| `draft.translation.thumbnailSrc.it` | No | When `pAppCode` is `E00003`: object or `` |
| `draft.translation.thumbnailSrc.it.imageTaskId` | Yes | When `pAppCode` is `E00003`: string; pattern `^[A-Za-z0-9_-]{8,80}$`; Reuse this requestId and the exact original input after interruption. Never change requestId to retry an uncertain write. |
| `draft.policy` | Yes | When `pAppCode` is `E00003`: object |
| `draft.policy.title` | Yes | When `pAppCode` is `E00003`: string; min length 3; max length 50 |
| `draft.policy.presentationalTitle` | Yes | When `pAppCode` is `E00003`: string; min length 3; max length 50; pattern `^[^\r\n]*$` |
| `draft.policy.translation` | No | When `pAppCode` is `E00003`: object |
| `draft.policy.translation.presentationalTitle` | Yes | When `pAppCode` is `E00003`: object |
| `draft.policy.translation.presentationalTitle.ko` | No | When `pAppCode` is `E00003`: string |
| `draft.policy.translation.presentationalTitle.en` | No | When `pAppCode` is `E00003`: string |
| `draft.policy.translation.presentationalTitle.ja` | No | When `pAppCode` is `E00003`: string |
| `draft.policy.translation.presentationalTitle.zh` | No | When `pAppCode` is `E00003`: string |
| `draft.policy.translation.presentationalTitle.zh-Hant` | No | When `pAppCode` is `E00003`: string |
| `draft.policy.translation.presentationalTitle.fr` | No | When `pAppCode` is `E00003`: string |
| `draft.policy.translation.presentationalTitle.es` | No | When `pAppCode` is `E00003`: string |
| `draft.policy.translation.presentationalTitle.vi` | No | When `pAppCode` is `E00003`: string |
| `draft.policy.translation.presentationalTitle.ru` | No | When `pAppCode` is `E00003`: string |
| `draft.policy.translation.presentationalTitle.it` | No | When `pAppCode` is `E00003`: string |
| `draft.policy.tierPrices` | Yes | When `pAppCode` is `E00003`: array; min items 1; max items 100 |
| `draft.policy.tierPrices[].tierLabelId` | Yes | When `pAppCode` is `E00003`: string; min length 1; max length 160; pattern `^[A-Za-z0-9_-]+$`; Exact resource identifier returned by this operation, never a title, unrelated row ID or URL. |
| `draft.policy.tierPrices[].amount` | Yes | When `pAppCode` is `E00003`: string; pattern `^(0\|[1-9]\d{0,9})(\.\d{1,2})?$` |
| `channelCode` | Yes | When `pAppCode` is `E00003`: string; min length 1; max length 512; The exact channelCode selected through channel discovery. Do not supply a URL, channel numeric ID, account ID or credentials. |

## Input example

Illustrative single-option draft. Replace image and shipping IDs with completed/observed same-context values. The earlier upload dry run does not create shop-image-001.

```json
{
  "channelCode": "selected-channel",
  "pAppCode": "X00004",
  "draft": {
    "name": "Sample notebook",
    "slug": "sample-notebook",
    "price": "1000",
    "originalPrice": null,
    "imageTaskIds": ["shop-image-001"],
    "returnPolicyContent": "Use the existing store return policy.",
    "shippingPolicyId": "observed_shipping_policy",
    "saleStatus": "DISCONTINUED",
    "visibilityStatus": "DISABLED",
    "options": {"kind": "single", "sku": "NOTEBOOK-01", "quantity": 10}
  }
}
```

## Optional creation SEO fields

| Optional draft field | Owner contract |
| --- | --- |
| seoTitle | String up to 100 UTF-16 units; explicit empty string allowed. |
| seoDescription | String up to 5000 UTF-16 units; explicit empty string allowed. |
| seoKeywords | Array of trimmed nonempty strings. Comma-joined length at most 5000 UTF-16 units; empty array allowed. Order and duplicates are preserved. |
| seoImgAltText | String up to 300 UTF-16 units; explicit empty string allowed. |

None accepts null. The three plain string fields are not trimmed. Omitted keys remain absent from the draft and generated request; there are no new defaults or implicit name/summary copies. The source UI can prefill title/description on name/summary blur, but this adapter does not synthesize those values. Partial metadata leaves other SEO keys absent. Legacy X00002 and ticket-event drafts do not gain these fields.

Any metadata edit requires preparing the entire draft again and using the newly returned revision. In the owner workflow, requested metadata joins exact product/image/option/stock readback. Missing keys, changed keyword order/duplicates, or null in place of an explicit empty string remain pending. Creation receipts and sent-once recovery are unchanged. This does not implement a search-engine indexing result, visitor metadata rendering or exact deletion/restoration.

The following input-schema illustration demonstrates explicit blanks and retained duplicate keyword order. Real image/dependency identities and the existing prerequisites are still required.

```json
{
  "channelCode": "selected-channel",
  "pAppCode": "X00004",
  "draft": {
    "name": "Sample notebook",
    "slug": "sample-notebook",
    "price": "1000",
    "originalPrice": null,
    "imageTaskIds": ["shop-image-001"],
    "returnPolicyContent": "Use the existing store return policy.",
    "shippingPolicyId": "observed_shipping_policy",
    "saleStatus": "DISCONTINUED",
    "visibilityStatus": "DISABLED",
    "options": {"kind": "single", "sku": "NOTEBOOK-01", "quantity": 10},
    "seoTitle": "Notebook",
    "seoDescription": "",
    "seoKeywords": ["notebook", "paper", "notebook"],
    "seoImgAltText": ""
  }
}
```

## Initial buyer input and add-ons

These are initial child records within the existing CREATE; they do not add new tools or enable adding groups/items to an existing product. It reuses the owner field constraints, allows at most one input/group and validates ordered1–3-item arrays with isRequired:false.

| Optional draft field | Complete object when supplied |
| --- | --- |
| inputOption | One title and placeholder, each trimmed and 1–50 UTF-16 units. This creates one buyer-input field. |
| addons | One title, trimmed 1–50 UTF-16 units, and items containing 1–3 choices in the desired order. |
| addons.items entry | name trimmed 1–50 UTF-16 units; additionalPrice as a nonnegative decimal string; explicit saleStatus ACTIVE or DISCONTINUED. |

Neither object accepts null, existing child IDs, caller-selected ranks, requiredness or arbitrary extra fields. Add-ons use one group with isRequired:false; child ordering is derived from the input. Prices use the verified currency and the existing add-on rule: zero through9,999,999,990, KRW integer strings in steps of100 and USD steps of0.01. KRW decimal notation is rejected even for an integral value. These bounds differ from the base product/variant price rules. USD prices are normalized to two decimals; no currency conversion or buyer charge occurs.

Omitted inputOption/addons introduce no parsed defaults and retain the older empty request arrays. They can compose with single/combined variants and explicit SEO in the owner workflow. Editing any option requires fresh preparation of the complete draft and a new revision. The existing image, linked-record, stock and sale/visibility checks remain required.

The durable returned product ID identifies the created aggregate. Two stable reads of that exact product validate child business/numeric IDs, parent/store/currency identity, uniqueness, order, requested title/placeholder/price/status and unchanged surrounding product state. Generated child identities and timestamps are excluded only from the requested-value projection; child IDs remain in the full stability comparison. Missing parent identity cannot be recovered by matching child text or IDs from a search.

Illustrative input-schema draft with initial options. Use real same-context image and shipping identities.

```json
{
  "channelCode": "selected-channel",
  "pAppCode": "X00004",
  "draft": {
    "name": "Sample notebook",
    "slug": "sample-notebook",
    "price": "1000",
    "originalPrice": null,
    "imageTaskIds": ["shop-image-001"],
    "returnPolicyContent": "Use the existing store return policy.",
    "shippingPolicyId": "observed_shipping_policy",
    "saleStatus": "DISCONTINUED",
    "visibilityStatus": "DISABLED",
    "options": {"kind": "single", "sku": "NOTEBOOK-01", "quantity": 10},
    "inputOption": {"title": "Gift message", "placeholder": "Enter a short message"},
    "addons": {
      "title": "Gift wrapping",
      "items": [{"name": "Paper wrap", "additionalPrice": "100", "saleStatus": "ACTIVE"}]
    }
  }
}
```

Sent-once creation, historical status and observation-only recovery are unchanged. There is no automatic cleanup, rollback or identity-preserving removal.