Developers who come to Acumatica Mobile expecting a native mobile codebase — Swift, Kotlin, React Native project files somewhere — are always a little surprised by what they actually find: one generic mobile client app, downloadable from the app stores, that renders whatever screens your Acumatica instance exposes to it through a contract described in Swagger/OpenAPI. There's no per-client app to build or ship. The "app" is a rendering engine; your instance is the content.
The mobile app is a Swagger-driven client, not a bespoke build
When a user adds an Acumatica instance to the mobile app (by URL, same as logging into the browser), the app requests the instance's mobile API definition — a Swagger/OpenAPI document describing every mobile-enabled screen's fields, containers, and available actions — and renders the UI from that contract at runtime. This is the same underlying idea as the platform's contract-based REST API, reused for mobile rendering: the client doesn't hardcode what a Sales Order screen looks like, it asks the server and draws whatever comes back.
The practical consequence: enabling a screen for mobile is a server-side configuration and customization task, not a client development task. You are never writing Swift or Kotlin. You are shaping what the server's mobile contract exposes, and the generic client renders it.
MSDL: patching the mobile screen definition
The Mobile Screen Definition Language (MSDL) is XML that patches a base screen's mobile container definitions — deciding which fields appear, in what containers (header, details grid, summary), with what input types, and which actions (like barcode scanning, discussed separately) attach to which fields:
<mobile>
<screen key="SO301000" primaryView="Document">
<container name="Header">
<field name="OrderNbr" />
<field name="CustomerID" />
<field name="OrderTotal" readOnly="true" />
</container>
<container name="Details">
<field name="InventoryID" />
<field name="OrderQty" />
<field name="UnitPrice" />
</container>
</screen>
</mobile>
This XML deploys inside a customization project, same as everything else — there is no separate "mobile deployment" pipeline. If you're building mobile support for a custom screen you've already extended for classic or Modern UI, the DAC and graph work is entirely reused; MSDL is purely presentation for the mobile renderer, the same way a classic ASPX screen definition is presentation for the browser.
Not every screen belongs on mobile, and the framework doesn't stop you from trying anyway
The generic-renderer model means technically almost any screen can get an MSDL patch and appear on mobile. Whether it should is a UX judgment the framework won't make for you. Screens with dense grids, many simultaneous conditional field states, or workflows requiring side-by-side comparison of many rows translate poorly to a phone-sized viewport no matter how carefully you patch the container definitions. The screens that succeed on mobile in my experience share a shape: single-record-at-a-time entry (a receipt, an expense claim, an inventory count line), a short field list, and a workflow that genuinely benefits from being done standing in a warehouse or on a job site rather than at a desk. Forcing a dense financial entry screen onto mobile because a client asked for "everything on mobile" produces something technically functional and practically unused.
Because the client renders from a server-generated Swagger document, a surprising number of "the mobile app is broken" tickets are actually contract issues — a field type mismatch, a required field the MSDL patch didn't account for, an action that exists in the graph but wasn't exposed in the mobile container. Before assuming a device or app-version bug, check the instance's mobile API definition (accessible via the standard OpenAPI endpoint pattern) to confirm the contract actually describes what you expect. Debugging the contract is almost always faster than debugging the device.
Actions and offline both build on this same contract
Custom PXAction buttons you've added via a graph extension can be exposed on mobile through the same MSDL container patching, appearing as buttons in the mobile UI and invoking your existing server-side action logic unchanged — you are not reimplementing business logic for mobile, only deciding whether and where it's visible. Offline mode (its own deep topic, given the real limitations involved) also builds on this same Swagger-described contract: the app caches a subset of the described screens and their data locally, then reconciles against the server contract on reconnect.
Version alignment matters here too
Because the mobile app is a single generic client shared across every Acumatica customer, and it renders from a Swagger contract your specific instance's version produces, mismatches between the mobile app's supported API version and your instance's actual version are a real source of "it worked last week" tickets after either side updates independently. Acumatica maintains compatibility across a reasonable version range, but on any client project running an older instance version, checking the mobile app's stated compatibility range before troubleshooting a rendering problem as a customization bug saves real time.
Wrapping up
Acumatica Mobile is not a codebase you build per client — it's a generic renderer consuming a Swagger/OpenAPI contract your instance generates, shaped through MSDL patches inside your ordinary customization projects. Enabling a screen for mobile is configuration and presentation work layered on business logic you likely already wrote for the browser, and most "mobile is broken" debugging starts more productively at the contract than at the device.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.