API REFERENCE

Initialisation

The mobile application begins the conversation by sending the first packet. This will contain the function name "setConnection" along with some detail about the device being used.

{
    "method":         "setConnection",
    "bundleID":       "xpedite.software",
    "uuid":           "mobile phone UUID",
    "bounds":         "screen dimensions in logical pixels",
    "xpediteVersion": 1
}
When receiving a packet we recommend extracting the "method" entry — it identifies the local function you should run. In this first packet the method will always be "setConnection". Create a function called setConnection, call it, and pass the array. The setConnection function typically initialises a session by creating a GUID which will be included in all successive packets as the "token".

NOTE: The mobile app can remain running long after your web server session expires, so implement your own session management using the GUID you have created. It will be included in every packet you receive as the "token" entry.

The packet you send back must include at least: a return code, a version number, the token, and a components entry indicating what to display next.

{
    "rc":         0,
    "version":    1,
    "token":      "08829e57-56ec-42a8-8b84-061981c054c8",
    "components": [{"type": "label", "text": "Hello world"}]
}

Regular conversation

Every response you send must include rc and components. The token is required after the initial setConnection exchange.

{
    "rc":         0,
    "token":      "08829e57-56ec-42a8-8b84-061981c054c8",
    "components": [{"type": "label", "text": "Hello world"}]
}

Every packet you receive will include the method and the token.

{
    "method": "addCustomer",
    "token":  "08829e57-56ec-42a8-8b84-061981c054c8"
}

Each response renders a completely fresh screen. All components listed in the components array are stacked top-to-bottom in the order they appear.

Top-level response entries

rc
Return code sent to the mobile app. A value of 0 indicates success. Any other integer causes an error dialog to be displayed.
{"rc": 0}
token
The session token generated in setConnection. The mobile app will verify this token on every response; a mismatch aborts the response.
{"token": "08829e57-56ec-42a8-8b84-061981c054c8"}
version
Your application version number (integer). When this number changes, any page cache stored on the device is invalidated and fresh content is downloaded.
{"version": 1}
title
Sets the navigation bar title for this screen. Omit this entry to hide the navigation bar entirely.
{"title": "Customer List"}
background
Sets the screen background colour using a 6-character hex colour code. The default is the system background (adapts to light/dark mode).
{"background": "#F5F5F5"}
id
A page identifier string. Required when using disposition for page caching. Also used as a duplicate-component guard within a single page.
{"id": "customer-list"}
disposition
Controls page caching on the device. Use "permanent" to cache indefinitely, or an expiry dict to cache for a fixed number of seconds. Requires id. When the server is unreachable, a cached page is served automatically.
{"disposition": "permanent"}
{"disposition": {"type": "expiry", "seconds": 3600}}
setDefaults
Sets session-wide defaults applied to all subsequent text components unless overridden at the component level. Set this once at the start of your session.
{
    "setDefaults": {
        "font":       "Helvetica",
        "fontsize":   16,
        "background": "#FFFFFF"
    }
}
images
Preloads images from URLs before the screen renders. Each entry requires an id (used to reference the image in components), a url (HTTPS), and optionally a load priority.
  • "load": "critical" — downloaded before the screen renders.
  • "load": "background" — downloaded after rendering (default).
{
    "images": [
        {"id": "logo",   "url": "https://my.app/images/logo.png",   "load": "critical"},
        {"id": "banner", "url": "https://my.app/images/banner.png", "load": "background"}
    ]
}
components
The array of UI components to render on screen. Components are processed in array order and stacked top-to-bottom. See the Component Types section for full details.
{
    "components": [
        {"type": "label",  "text": "Welcome"},
        {"type": "button", "text": "Continue", "method": {"function": "home"}}
    ]
}

Method dispatch

Buttons, table rows, and navigation entries all call the server using the same method dict. Every method call renders a completely fresh screen by default.

function
The server method name to call when this element is activated.
{"function": "listCustomers"}
parameters
Additional key/value pairs sent to the server with the method call.
{"function": "viewCustomer", "parameters": {"id": "123"}}

Full method dict example:

{
    "function":   "viewCustomer",
    "parameters": {"id": "123"}
}

Size specification

Most components accept a "size" dict. Omitting it uses a sensible default (typically full width). Components are stacked top-to-bottom automatically; the layout engine tracks the bottom edge of each placed component.

{"size": {"width%": 80, "height": 44, "centrex": 0}}
{"size": {"x+": 10, "width%": 50, "relative-height%": 100}}
width / height
Absolute size in logical pixels (points).
width% / height%
Percentage of the total screen width or height.
relative-width% / relative-height%
Percentage of the remaining space from the current x or y position. Useful for filling whatever space is left after other components are placed.
x / y
Absolute origin in logical pixels from the top-left of the screen.
x% / y%
Origin as a percentage of screen width or height.
x+
Horizontal offset from the right edge of the previous component.
y+
Vertical offset below the bottom edge of the previous component.
centrex / center-x / centre-x / centerx
Centre the component horizontally on screen (value is ignored).
centrey / center-y / centre-y / centery
Centre the component vertically on screen (value is ignored).

Component types

component-label
Displays a line or block of text. Multi-line by default; wraps automatically.
Keys: text (required), color, background, font, fontsize, align, size, id.
{
    "type":     "label",
    "text":     "Hello world",
    "color":    "#333333",
    "fontsize": 20,
    "align":    "centre",
    "size":     {"width%": 100, "height": 44}
}
component-image
Displays an image. Use id to reference a preloaded image, or url to download one at render time. If only width is specified, height is derived from the image aspect ratio.
{"type": "image", "id": "logo",                 "size": {"width%": 50}}
{"type": "image", "url": "https://...",          "size": {"width%": 100, "height": 200}}
component-button
A tappable button. When tapped, calls the method specified in method. If the method dict contains "formdata": true, the current screen's captured input is sent with the call.
Keys: text, style, color, background, font, fontsize, align, icon, method, size, id.
  • "style": "plain" — text only (default).
  • "style": "button" — bordered, rounded corners.
{
    "type":   "button",
    "text":   "Save",
    "style":  "button",
    "size":   {"width%": 60, "height": 44, "centrex": 0},
    "method": {"function": "save", "navigation": "root"}
}
component-textbox
A single-line text input field. Input is captured into form data under the name key. Can also be used standalone on a screen.
Keys: name (required), title, placeholder, value, keyboard, returnkey, onEnter, autotext, color, font, fontsize, align, focus, size, id.
{
    "type":        "textbox",
    "name":        "email",
    "placeholder": "you@example.com",
    "keyboard":    "email",
    "returnkey":   "next"
}
component-password
Same as textbox but renders as a secure entry field. Characters are briefly visible then masked; an eye button lets the user reveal the value.
Keys: same as textbox.
{"type": "password", "name": "pwd", "placeholder": "Enter password"}
component-scrollview
A scrollable container. Place any components inside it via the components array. If height is omitted the scroll view sizes itself to fit its content.
Keys: components, background, size, id.
{
    "type":       "scrollview",
    "size":       {"width%": 100, "height%": 60},
    "components": [{"type": "label", "text": "Long content..."}]
}
component-web
Renders a WKWebView. Supply either a URL to load or an inline HTML string.
Keys: web (URL), content (HTML string), background, size, id.
{"type": "web", "web":     "https://example.com",       "size": {"width%": 100, "height%": 80}}
{"type": "web", "content": "<h1>Hello</h1>", "size": {"width%": 100, "height": 400}}
component-table
Displays tabular data fetched from the server. Supports multiple columns, a fixed or scrolling column header, pull-to-refresh, and incremental pagination.
Keys: data (required), cell, header, clickRow, refresh, background, size, id.
{
    "type":     "table",
    "data":     {"dynamic": "listCustomers"},
    "refresh":  "Pull to refresh",
    "header": [
        {"text": "Name",  "width%": 60, "font": "headline"},
        {"text": "Score", "width%": 40, "align": "right", "scroll": "off"}
    ],
    "cell": [
        {"field": "name",  "width%": 60},
        {"field": "score", "width%": 40, "align": "right", "color": "#007AFF"}
    ],
    "clickRow": {"function": "viewCustomer", "selected": "id"}
}

cell / header column keys:

  • field — data field name from each row record (cell only).
  • text — static label text (header only).
  • width% — column width as a percentage of table width. Omit to share remaining width equally.
  • alignleft | centre | right. Default: left.
  • font — text style name (headline, body, footnote, etc.) or a font name.
  • fontsize — point size override (integer).
  • color — text colour (hex).
  • lines — number of lines; 0 = unlimited. Default: 1.
  • scroll"on" (header scrolls with data, default) | "off" (header fixed above table). All header entries must agree.

Data response (from the dynamic function):

{"rc": 0, "data": [{"name": "Alice", "score": 42}, ...], "max": 50}
  • data — array of row records.
  • max — include when returning a partial batch (more rows available). Omit on the final batch.

clickRow sends the selected row's field value to the server:

{"function": "viewCustomer", "selected": "id"}
component-form
A data-entry form rendered as a grouped table. Contains field components in its components array. On save, all captured field values are sent to the server under formdata.{formId}.
Keys: style, title, save, saveNavigation, cancel, cancelNavigation, components, size, id (required for save data).
  • "style": "inline" — optional title bar + Cancel/Save footer buttons.
  • "style": "dialog" — modal style with ✕ (cancel) and ✓ (save) in the header bar.
{
    "type":             "form",
    "id":               "customer-form",
    "style":            "inline",
    "title":            "Add Customer",
    "save":             {"function": "saveCustomer"},
    "saveNavigation":   "Save",
    "cancel":           {"function": "home"},
    "cancelNavigation": "Cancel",
    "components":       [...]
}

Form field types (used inside a form's components array):

section — creates a section header row:

{"type": "section", "title": "Personal Details"}

textbox — single-line text entry:

{"type": "textbox", "name": "firstname", "title": "First name", "placeholder": "Enter name", "value": "Alice"}

password — masked text entry:

{"type": "password", "name": "pwd", "title": "Password"}

textview — multi-line text entry:

{"type": "textview", "name": "notes", "title": "Notes", "placeholder": "Enter notes..."}

checkbox — boolean toggle:

{"type": "checkbox", "name": "active", "title": "Active customer", "value": "1"}

date — date picker. Value format: yyyy-MM-dd:

{"type": "date", "name": "dob", "title": "Date of birth", "value": "1990-06-15"}

select — picker wheel. Options must use string keys:

{
    "type":    "select",
    "name":    "country",
    "title":   "Country",
    "value":   "AU",
    "options": {"AU": "Australia", "NZ": "New Zealand", "US": "United States"}
}

radio — vertical radio button group. Options must use string keys:

{
    "type":    "radio",
    "name":    "gender",
    "title":   "Gender",
    "value":   "M",
    "options": {"M": "Male", "F": "Female", "X": "Other"}
}
component-navigation
Adds a nav bar button or an edge-swipe panel to the current screen. Behaviour is controlled entirely by the implementation dict.
Keys: implementation (required), components, effects, id.

implementation keys:

  • style"button" | "slidefrom" (required).
  • position"left" | "right" (required).
  • icon — SF Symbol name for the bar button, e.g. "ellipsis.circle", "plus".
  • image — local image ID for the bar button (takes precedence over icon).

style = "slidefrom" — edge swipe reveals a slide-in panel. Swipe back or tap the shade overlay to close:

{
    "type": "navigation",
    "id":   "main-menu",
    "implementation": {"style": "slidefrom", "position": "left"},
    "effects":    {"shade%": 40},
    "components": [
        {"type": "menuEntry", "text": "Customers", "icon": "customers", "method": {"function": "listCustomers"}},
        {"type": "menuEntry"},
        {"type": "menuEntry", "text": "Logout",                         "method": {"function": "logout"}}
    ]
}

style = "button" — adds a UIBarButtonItem. Single menuEntry calls the method directly; multiple entries show a dropdown menu:

{
    "type": "navigation",
    "implementation": {"style": "button", "position": "right", "icon": "ellipsis.circle"},
    "components": [
        {"type": "menuEntry", "text": "Add",    "symbol": "plus",            "method": {"function": "addCustomer"}},
        {"type": "menuEntry", "text": "Search", "symbol": "magnifyingglass", "method": {"function": "search"}}
    ]
}

{
    "type": "navigation",
    "implementation": {"style": "button", "position": "right", "icon": "plus"},
    "components": [
        {"type": "menuEntry", "method": {"function": "addCustomer"}}
    ]
}

menuEntry keys:

  • text — label. With method: interactive entry. Without: bold section header.
  • method — method dict; makes the entry tappable.
  • icon — local image ID shown left of text (slidefrom panel only).
  • symbol — SF Symbol shown beside the item (button dropdown only).
  • No keys — renders as a horizontal divider line.

effects:

  • shade% — 0–100. Semi-transparent overlay behind the panel (slidefrom only). Tapping it closes the panel.

Caching by id: If a navigation component includes an id, its full definition is cached on the device. On subsequent pages send only {"type":"navigation","id":"main-menu"} to reload it from cache.

Common keys

align
Text alignment. Valid values: left, right, centre, center, justify.
{"align": "left"}
autotext
Only valid with textbox. Set to "disable" to turn off autocorrect and autocapitalise (useful for usernames, codes, etc.).
{"autotext": "disable"}
background
Background colour for the component. 6-character hex. Default: system background.
{"background": "#FFFFFF"}
color / colour
Text colour. Either spelling is accepted. 6-character hex. Default: system label colour.
{"color": "#000000"}
focus
Include on a textbox to give it keyboard focus immediately when the screen appears.
{"type": "textbox", "name": "search", "focus": true}
font
Font family name. If the font is not found the system default is used. Common values: "Helvetica", "Georgia", "Courier". See developer.apple.com/fonts for the full list.
{"font": "Helvetica-Bold"}
fontsize
Font size as an integer (points). Do not include units.
{"fontsize": 16}
id
Optional identifier for any component. Included in error messages for easier debugging. Required on forms for save-data routing; required on navigation components for caching.
{"id": "customer-name-field"}
keyboard
Only valid with textbox. Sets the keyboard type shown when the field is focused. Values: email, number, phone, url, default.
{"keyboard": "email"}
name
Required on all form field types. The key used when submitting captured form data back to the server. Use unique values per form.
{"name": "customer_name"}
onEnter
Only valid with textbox. The id of the next field to focus when the return key is tapped, enabling keyboard navigation between fields.
{"onEnter": "password-field"}
options
Used with select and radio field types. A flat dict of "key": "Display Label" pairs. Keys must be strings. Options are sorted by key before display.
{"options": {"1": "Option A", "2": "Option B", "3": "Option C"}}
placeholder
Hint text shown inside a text field when it has no value.
{"placeholder": "Enter the customer's first name"}
refresh
Only valid with the table component. Adds a pull-to-refresh control with the given label. Pulling down resets and reloads all table data from the server.
{"refresh": "Pull to refresh"}
returnkey
Only valid with textbox. Sets the label on the keyboard return key. Values: next, done, go, search, default.
{"returnkey": "next"}
size
Positions and sizes a component. See the Size Specification section above for full details.
{"size": {"width%": 80, "height": 44, "centrex": 0}}
time
Optional. Unix timestamp of when the server processed the request.
{"time": 1744531200}
title
At the top level: sets the navigation bar title. Within a form: the page/form heading. Within a form field: the label displayed beside the field.
{"title": "Customer Details"}
value
Pre-fills a field with an existing value. Format depends on field type: date fields use "yyyy-MM-dd", checkboxes use "1" / "0", select and radio use the option key string.
{"value": "1990-06-15"}
cancel / save
Used within a form. Each value is a method dispatch dict called when the respective button is tapped. Captured form data is sent automatically.
{"save":   {"function": "saveCustomer"},
 "cancel": {"function": "home"}}
cancelNavigation / saveNavigation
Label text for the Cancel and Save buttons in a form. Defaults to "Cancel" and "Save".
{"saveNavigation": "Confirm", "cancelNavigation": "Discard"}