Menu Config as Code and Batch Imports
This is an advanced workflow for plugin installation, CI/CD, app upgrades, or config files that import a complete menu at once.
If you are building a normal admin page, prefer the incremental methods: menus.configs/items/views/loadApis/actions/responses. That path is easier to understand; see Manage Menus. If you only need to understand what load, actions, and response mean, see Configure APIs and Response Fields.
When to use MenuConfigInput
MenuConfigInput means “I already have the whole menu config and want to save it as one model.” It is not the best fit for saving one field at a time from a normal admin form.
Complete config example
A full config can declare menus, views, page load APIs, actions, and response fields together:
Field guide
This config expresses these things:
load.resource must be an api: resource, for example api:GET:/api/orders. That lets Vext route guards, role-menu authorization, and response-field projection use one resource ID. actions[].resource can be a backend API or a pure UI resource; use api: for backend calls.
Response field syntax
Inside MenuConfigInput, response fields support array form and object form:
Array form works when the endpoint returns an object or an array directly. Field names support dot paths such as buyer.name.
For paginated responses, use object form:
target points to the array to project, and preserve keeps outer structural fields that do not require field grants. The example above filters each row under items and preserves total as pagination metadata.
Note: array form is only for inline config inside MenuConfigInput. If you use the incremental method menus.responses.set(), write object form even without target: response: { fields: [...] }.
Preview and save a full config
menus.config.preview(config) computes impact without writing; menus.config.save(config, options) writes the full config.
Execution must include the preview’s expected and previewToken so an administrator cannot save a stale menu model.
Change, delete, and batch update
Reads, deletes, and batch updates use the advanced menus.config entrypoint:
Single saves fit a complete menu import. menus.config.previewChanges() / menus.config.applyChanges() fit plugin installation, app upgrades, and config package imports where several module menus change together.
After saving the config, the role still has no permission. If page APIs, action APIs, and response fields are still unclear, read Configure APIs and Response Fields first. The next usual step is Authorize Role Menus, where views, APIs, actions, and response fields are granted to roles.