design_menu_layout_apply — publish one device's menu connections
Set one device's template and both menu slots together, then read the stored result. First call design_menu_layout_get for the same channel and device. Prepare menu definitions and their contents through their own workflows before connecting them here.
Input
| Field | Type | Required | Constraint |
|---|---|---|---|
requestId |
string | Yes | 8–80 ASCII letters, digits, underscores or hyphens. Preserve it for this operation. |
channelCode |
string | Yes | Nonempty code of the channel just read. |
device |
enum string | Yes | W, M or A, matching the read. |
expectedRevision |
string | Yes | Lowercase 64-character hexadecimal revision from that read. |
menuTemplateType |
string | Yes | Nonempty type from get's available templates. |
primaryMenuId |
positive integer | Yes | Candidate menu ID, or the existing ID in this same slot. |
secondaryMenuId |
positive integer or null |
Yes | Candidate menu ID, the existing ID in this same slot, or explicit null to clear. |
dryRun |
boolean | No | Defaults to false; true prepares a plan without publishing. |
The input is strict; extra fields are rejected. Both slots must be explicit even when unchanged. Omission is not preservation, 0 is not a clearing value, and menu-item IDs cannot substitute for menu IDs. A template with secondaryMenu:false requires secondaryMenuId:null.
{
"requestId":"example-menu-layout-001",
"channelCode":"selected-channel-code",
"device":"W",
"expectedRevision":"0000000000000000000000000000000000000000000000000000000000000000",
"menuTemplateType":"W1_0003",
"primaryMenuId":101,
"secondaryMenuId":102,
"dryRun":true
}
This is an illustrative input, not an executed transcript. Replace the channel, zero revision, template and numeric IDs with the same get result. This template supports a secondary menu only if it is available on the selected channel/device. To retain an existing out-of-list menu, keep its ID in its original slot; moving that unlisted ID to another slot is rejected.
For a template-only change, explicitly carry forward both current slot IDs. If the new template does not support Secondary, clearing that connection is an additional effect of choosing it; send null only when that matches the intended change. Each device change requires its own read, revision and request ID.
Plan and publication
The get tool's connection, selected-channel, role and origin requirements apply. A new request reads the state, compares the layout revision and validates the template/slot choices. A new dry run returns success/PLAN_READY, environment, channel, device and body:{menuTemplateType,primaryMenuId,secondaryMenuId}. It creates no task and sends no write.
Real execution saves a menu-design task and reads again. If the same layout already has the requested body, it can complete without writing. Otherwise it requires the original revision, revalidates choices, records phase:sending and sends one PUT:
/seller/api/v1/channel-management/design-preferences/menu-design-layouts/{layoutId}
The layout ID comes from get's verified state, not a caller-supplied input. Menu transport checks connection and the exact selected-channel credential before and after the request; a post-dispatch context change remains an unknown write outcome. The request uses the general API origin, selected-channel bearer and channel-ID header. Its body includes the template and both slots. It creates no menu, edits no menu items, refreshes no credentials and sends no separate site-launch or publication call beyond this layout update.
After the PUT, the workflow rereads menus/templates/layout and requires the same layout ID and all three requested body values. These read/compare/write steps are not an atomic server transaction; they cannot rule out a competing write after the final check. There is no automatic rollback. Separate device operations can finish independently.
Completion and saved plans
Completion returns success/MENU_DESIGN_APPLIED, task ID, taskType:menu-design, environment, channel, device, layout:{id,menuTemplateType,primaryMenuId,secondaryMenuId}, revision, and verification:{confirmed:true,method:menu_design_read}. There is no changed field. Success can mean the intended layout was already present or a sent change was later observed; it does not prove which actor produced it.
Replaying a completed apply/resume checks current channel context but returns the saved historical result without freshly reading the layout. Use get to establish present state. Stored readback does not prove desktop/mobile/app rendering, visitor access or a visual preference was satisfied.
A dry run with an existing matching job returns PLAN_READY, task ID/type, phase, existingPhase and saved body, with the history fields described below. It checks context and input identity, but does not reread or revalidate the layout/candidates. New-plan environment/channel/device fields are omitted.
Non-demo get/completion results with a resolved target return one menu-design destination. A new dry run has no task type/result code identifying that route, while an existing-job dry run has no channel metadata; both therefore return unavailable navigation rather than a substitute home URL. Task status also reports unavailable navigation and removes saved navigation metadata from its direct lastResult. The shared wrapper does not change the stored journal. URLs are navigation hints, not completion evidence.
Recovery
Use task_status and task_resume with the original task ID and taskType:menu-design. Preserve the connection, channel, device, original revision and all other business inputs. The saved fingerprint ignores only dryRun; changing another input under the same request ID produces TASK_CONTEXT_CHANGED.
| Saved phase | Behavior |
|---|---|
prepared |
Read again. Complete without writing if the target is already observed; otherwise require the original revision and current valid choices before sending. |
sending |
Read first. Complete if the same layout matches the requested body; otherwise return MENU_DESIGN_OUTCOME_UNKNOWN without resending the PUT. |
done |
Return the historical saved result. |
A definite rejected/not-sent PUT failure restores prepared; unknown or unclassified failures retain sending. A read failure after dispatch also leaves the task sent; do not infer from that read error that the write never occurred. Status contains phase and last result, not a step array. pending is saved unfinished work, not proof of a background worker. A fresh dry run has no saved task.
| Code | Meaning and next step |
|---|---|
INVALID_INPUT |
Correct invalid/missing fields; SDK validation may reject earlier. |
MENU_TEMPLATE_UNAVAILABLE |
The template is unknown, for another device, or absent from the current candidates. |
SECONDARY_MENU_UNSUPPORTED |
Use an intended supported combination; an unsupported template requires null. |
MENU_UNAVAILABLE |
A chosen ID is neither a candidate nor the existing ID in that same slot. |
DESIGN_CONFLICT |
The observed layout differs from the original revision. Read current state and inspect the original task. |
TASK_CONTEXT_CHANGED, CONNECTION_CHANGED, MENU_CONTEXT_CHANGED |
The saved inputs, account or target binding no longer match. |
MENU_DESIGN_OUTCOME_UNKNOWN |
A sent update remains unverified and will not be automatically repeated. |
MENU_DESIGN_VERIFICATION_MISMATCH |
Post-publication readback does not match the target; the outcome remains unknown. |
Other read/access errors follow get's rules. Internal failures can include task/channel/device metadata and phase; outer failures can omit them. Do not use a new request ID to force a repeat of an uncertain publication. Resume is mutation-capable.
Saved plan replay
An existing matching task's dryRun returns historical saved plan/progress,
historical:true, replayed:true and false current verification. It has no current
console/action link and does not read present business state, repeat effects or
change the journal. Saved phase/progress and existingPhase aliases remain where
applicable. Follow nextStep for a current observation; retain the original task
ID for uncertain-outcome recovery. A new task keeps normal fresh-plan validation.
nextStep: design_menu_layout_get retains the original channel and W/M/A device; saved layout body does not validate current candidates.
Saved record identity
Existing apply or dry-run calls and task status/resume require both the
saved task ID and saved input requestId to match the requested ID. A mismatching
or malformed saved identity returns TASK_STATE_UNVERIFIED before workflow
context or business-state reads. Preserve the original record for inspection;
do not rename/edit it, try its embedded ID or create a replacement request to
bypass the error. The workflow does not repair or resend the record. Valid
matching records keep their existing recovery behavior.
Inputs
| Field | Required here | Contract |
|---|---|---|
device |
Yes | W, M, A; W = desktop web, M = mobile web, A = Android/iOS app. |
menuTemplateType |
Yes | string; min length 1; A type returned in get.templates. |
primaryMenuId |
Yes | integer; greater than 0; An ID from get.menus, or the existing get.layout.primaryMenuId. This is not a menu-item ID. |
secondaryMenuId |
Yes | integer; greater than 0 or null |
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. |