Appearance
Schema Reference
An Axiomers app is defined by a schema: a JSON array of collections. Everything you build in the visual editor — fields, views, actions, formulas — is stored as this JSON, and the same JSON can be read, written, or generated directly. This page is the exhaustive reference for that format. For a walkthrough of the visual editor, start with Collections & Fields, Views, Actions & Workflows, and Expressions.
This page is written to be precise enough for an AI assistant to draft a valid schema from a plain description of an app.
Collection
A collection is one kind of record (customers, orders, visits…).
json
{
"name": "customers",
"label": "Customers",
"icon": "people",
"order": 1,
"schema": [],
"actions": [],
"views": [],
"defaultView": "table"
}| Property | Required | Meaning |
|---|---|---|
name | yes | Unique machine key, snake_case. Used in formulas and as the table name. |
label | yes | Human-readable name. |
icon | no | A Material icon name. |
order | yes | Sort order in the sidebar. Also the sync order: a collection that others reference should have a lower order than the collections that reference it. |
schema | yes | The fields — an array of field definitions. |
actions | yes | Buttons — an array of action definitions. |
views | yes | Ways to look at the records — an array of view definitions. |
defaultView | yes | The name of the view that opens first. Must match one of views[].name. |
isUserProfile | no | true on the single collection that holds one record per signed-in user. |
nav | no | Navigation options. Where the collection appears: sidebar (laptop menu, default true), menu (phone hamburger menu, default follows sidebar), bottom (phone bottom bar, default false). Order in each: order (sidebar), menuOrder and bottomOrder (each defaults to order). Also onlyIf (a formula; the item is hidden when it is false), label and icon. The bottom bar shows at most 5 items. The Navigation designer writes these keys. |
serverManaged | no | Set by the platform on system collections such as payments (see Payments). People can read these records but only the server can write them. Don't set it yourself, and don't name your own collection payments. |
Fields
Each entry in a collection's schema array is a field definition:
json
{
"key": "status",
"label": "Status",
"type": "enum",
"description": "Where the order is in its life cycle",
"required": true,
"typeOptions": {
"values": [
{ "value": "draft", "label": "Draft", "color": "grey" },
{ "value": "confirmed", "label": "Confirmed", "color": "green" }
]
},
"initialValue": "\"draft\""
}| Property | Meaning |
|---|---|
key | The field's internal name. Unique within the collection; can't be changed later. |
label | What people see as the field's name. |
type | One of the field types below. |
description | Help text. In a questionnaire it becomes the question text. |
required | Can't be left blank. |
readOnly | Shown, but not editable on forms. |
isLabel | Marks the record's short recognizable name (one per collection) — shown in reference pickers. |
labelExpression | A formula that overrides label with a computed value. |
typeOptions | Options that depend on type — see below. |
computed | { "enabled": true, "expression": "…" } — the value is calculated from a formula instead of typed in. |
initialValue | A formula evaluated once when the create form opens, to pre-fill the field. |
showIf | A formula; the field is hidden (and its value cleared) when it is false. |
validIf | A formula; the field is invalid on submit when it is false. |
validMessage | The error shown when validIf fails. |
Every record also has built-in fields you can reference in formulas: id, ownerId, updatedAt, isDeleted.
Field types
| Type | Stores | typeOptions |
|---|---|---|
text | A string | minLength, maxLength, placeholder, mask, enableScanner (adds a QR/barcode scan button) |
longtext | A multi-line string | same as text |
richtext | Sanitized HTML from a formatting editor | none |
number | A number | min, max, step, prefix, suffix, decimals |
price | A number shown as currency | defaultCurrency, allowedCurrencies, decimals |
boolean | true / false | none |
date / datetime / time | A date, a date and time, or a time of day | none |
enum | One of a fixed set of values (a string) | values |
multienum | Several of a fixed set of values (an array of strings) | values |
ref | A link to one record in another collection (its id) | collection, displayField, … |
multiref | Links to several records in another collection (an array of ids) | collection, displayField, … |
image / file | An uploaded file | accept, maxSizeMb, multiple |
drawing | A signature or sketch, stored as an image | strokeColor, strokeWidth, background, maxSizeMb |
geolocation | { "lat": number, "lng": number } captured from the device or picked on a map (with place search) | accuracy (low/medium/high), timeout |
address | { "country", "state", "city" } | none |
phone | One string, dial code plus number, e.g. "+2349071805738" | defaultDialCode (e.g. "+234") — the country code an empty field starts on. A number already saved keeps its own code, and a code the user picked earlier on their device takes priority. |
barcode | A string, rendered as a barcode or QR code | format (qrcode, code128, ean13, upc), showValueLabel, width, height |
table | An array of row objects you type in | columns: [{ "key", "label" }] |
list | Virtual, always computed — a list of values from related records | displayField, collection, sort |
completelist | Virtual, always computed — an embedded table of related records | collection, columns, sort |
values for enum and multienum is an array of { "value", "label", "color"?, "icon"? }.
One choice or several?
There is no "allow multiple" flag on enum or ref for new fields — multiple selections are their own types:
- One choice from a fixed set →
enum. Several ("tick all that apply") →multienum. - One related record →
ref. Several related records →multiref.
multienum takes the same typeOptions as enum, and multiref the same as ref, just without multiple.
ref and multiref options
json
{
"key": "customer",
"label": "Customer",
"type": "ref",
"typeOptions": {
"collection": "customers",
"displayField": "full_name",
"searchField": "phone",
"barcodeSearch": false,
"isDistinct": false,
"suggestedValues": "EQUAL({status},\"active\")",
"defaultValue": "{_THISUser.id}"
}
}| Option | Meaning |
|---|---|
collection | The collection to link to. It must exist in the schema. |
displayField | The field shown as each option's label. |
searchField | The field matched when the user types in the picker (defaults to displayField). |
barcodeSearch | Adds a scan button that searches searchField. |
suggestedValues | A formula evaluated per candidate record to filter the picker's options. |
defaultValue | A formula that pre-selects a value when the form opens. |
isDistinct | Hides any option that another record in this collection already uses through this field (for multiref, any item in another record's list), and rejects it on save. The record being edited keeps its own value. It's a check against the records on the device, so two people offline can still pick the same item before they sync. |
multiref has a few limits compared with ref:
- Dot-traversal (
{field.prop}) only works through a plainref, not amultiref. A bare{multirefField}still works and gives the array of ids. - The
navigate_refaction follows a plainrefonly. - A
multirefcan't be theforeignKeyinREF_ROWS(...). multienumandmultireffields are left out of CSV import, inbound webhooks, and the "colour by" / "status badge" pickers on calendar and card views (those need exactly one value).
When you need any of these, use ref.
Virtual fields
list and completelist hold no data of their own. A completelist must have computed: { "enabled": true, "expression": "…" } — almost always REF_ROWS("otherCollection", "foreignKeyOnThatCollection") — otherwise it renders nothing.
Views
A view is one way of looking at a collection's records.
json
{
"name": "table",
"type": "table",
"sections": [
{ "order": 1, "items": [
{ "order": 1, "type": "field", "key": "full_name" },
{ "order": 2, "type": "action", "key": "edit" }
] }
],
"sort": { "field": "full_name", "dir": "asc" },
"pagination": { "enabled": true, "limit": 25 }
}| Property | Meaning |
|---|---|
name | Identifier. Unique within the collection. |
type | detail, card, image-card, table, calendar, chart, dashboard, or questionnaire. There is no list type — use table for any tabular listing. |
sections | Ordered groups of items. An item is { "order", "type": "field" | "action", "key" }; the key must exist in the collection's fields or actions. A section can also have a label and an onlyIf formula. |
filterFields | Field keys to expose as filter controls above the view (not for detail). |
showIf | A formula; the whole view tab is hidden when it is false. |
filterExpr | A formula evaluated per record; records where it is false are hidden. |
pagination | { "enabled": boolean, "limit": number }. |
sort | { "field": string, "dir": "asc" | "desc" }. |
Every collection needs a detail view (conventionally named detail) — it's the only way to open a single record. Avoid making it the defaultView: it can't list records, so people would see nothing on open. Use table, card, calendar, chart, dashboard, or questionnaire.
Layouts
| View type | Extra property | Shape |
|---|---|---|
card, image-card | cardLayout | { "title": key, "subtitle"?: key, "description"?: key, "status"?: key, "image"?: key } — status must be an enum, image an image field |
calendar | calendarLayout | { "startDate": key, "title": key, "startTime"?: key, "endDate"?: key, "endTime"?: key, "color"?: key or color name, "defaultMode"?: "month" | "week" | "day" } |
chart | chartLayouts | An array of { "type": "bar" | "line" | "pie" | "doughnut", "labelField": key, "valueField"?: key, "color"?: string, "showLegend"?: boolean }. Omit valueField to count records per label. |
dashboard | dashboardPanels | An array of panels, below |
Card and image-card views are laid out by cardLayout alone. Their sections aren't used, so leave it as an empty array.
color on a chart applies to line charts only; bar, pie and doughnut charts colour each label automatically. To colour by status, set color on the enum field's own values instead.
Dashboard panels — each has a type (view or stat) and optionally col (the width out of 12: 3, 4, 6 or 12), title, showIf, filter (a formula), sort and actions (keys of collection-scoped actions). A view panel also takes viewName and limit; a stat panel takes field and aggregate (count, sum, avg, min, max).
Questionnaire views
A questionnaire view is a multi-step, one-question-at-a-time data-entry wizard — like a survey or intake form. Use it for interviews, assessments, checklists, inspections, or any long form that is easier to fill in step by step.
json
{
"name": "intake",
"type": "questionnaire",
"sections": [
{ "order": 1, "label": "About the patient", "items": [
{ "order": 1, "type": "field", "key": "full_name" },
{ "order": 2, "type": "field", "key": "date_of_birth" }
] },
{ "order": 2, "label": "Symptoms", "items": [
{ "order": 1, "type": "field", "key": "symptoms" }
] }
],
"listFields": [
{ "order": 1, "type": "field", "key": "full_name" }
]
}- Each section is one step. The section's
labelis the step title and itsitemsare the questions asked on that step. - The question text is the field's
description, falling back to itslabelwhen there is no description. Keeplabelshort (it's still used in tables and filters) and put the full question indescription, e.g. labelCause of death, descriptionWhat was the main cause of death?. - Validation runs per step (
required,validIf) before the user can continue, and again on submit. listFieldsare the columns shown in the list of already-submitted records that the view opens on. It is separate fromsections. If omitted, the first step's fields are used.- Every field type works inside a questionnaire, including
multienumandmultiref. - Answers are saved exactly like a normal create/edit form, so a questionnaire can sit alongside table or card views of the same collection.
Actions
An action is a button. Each collection should include the three system actions — delete (data/delete), edit (app/navigate_edit) and create (app/navigate_create), all with "isSystem": true — unless the collection is deliberately read-only.
json
{
"key": "mark_paid",
"label": "Mark paid",
"icon": "paid",
"type": "data",
"onlyIf": "EQUAL({status},\"confirmed\")",
"needsConfirmation": true,
"confirmMessage": "Mark this order as paid?",
"actionConfig": {
"type": "set_field",
"updates": [ { "field": "status", "value": "\"paid\"" } ]
}
}| Property | Meaning |
|---|---|
key, label, icon, color | Identity and appearance. |
type | data, external, or app. |
onlyIf | A formula; the button is hidden when it is false. |
needsConfirmation, confirmMessage | Ask before running. |
scope | record (default — a button per record) or collection (shown at the bottom of dashboard panels). |
trigger | manual (default, a button click), or afterCreate / afterUpdate / afterDelete to run automatically after that event, with no button. |
actionConfig | Depends on type — see below. |
Data actions
actionConfig.type | Options |
|---|---|
set_field, bulk_set_fields | updates: [{ "field", "value": formula }]. Bulk also takes expression (a COLLECTIONSELECT). |
delete, bulk_delete | Bulk takes expression. |
create_record, bulk_create_record | collection and mappings: [{ "targetField", "sourceExpression": formula }]. Bulk also takes expression. |
form_action | formTitle, formFields (full field definitions, referenced as {_FORM.key}), and updates. |
External actions
actionConfig.type | Options |
|---|---|
phone, email, url | target: a formula resolving to the number, address, or URL. |
http_request | target (a fixed URL string, never a formula), method (GET, POST, PUT, PATCH, DELETE), headers and queryParams ([{ "key", "value", "secret" }]), body ([{ "field", "value" }]), responseMapping ([{ "field", "path" }], where path is a dot-path into the { ok, status, body } response), and optionally responseCollection to create a new record instead of updating the current one. |
payment | amountField (the key of a stored number or price field on this collection, in naira; a computed field can't be used), optional description, and target set to "". The amount is read from the saved record on the server. See Payments & Earnings. |
For a secret header or query parameter (an API key, a token), set "secret": true and leave value as "". The real value is entered later in the admin secrets screen and never appears in the schema.
App actions
actionConfig.type | Options |
|---|---|
navigate_detail, navigate_edit, navigate_create, navigate_list | Optional collection. |
navigate_ref | refField — follows a plain ref field on this collection to its target record. |
navigate_by_id | collection and targetIdExpression — a formula resolving to the target record's id. Use for reverse relations navigate_ref can't reach, e.g. FIRST(SELECT("stock_items","id",EQUAL({product.id},{_THISRECORD.id}))). |
run_actions | actions: an array of action keys, run in sequence. |
export_pdf | template (HTML with <<{[field]}>> tokens) and filename (a formula). |
open_create | collection, prefill: [{ "key", "expression" }], and optionally afterSubmitNavigate (back, list, detail) with afterSubmitCollection. |
Expressions
Formulas appear in computed.expression, initialValue, showIf, validIf, onlyIf, filterExpr, action values, and suggestedValues / defaultValue. They are spreadsheet-style function calls with {field} references.
There are no infix operators. +, -, *, /, >=, <=, ==, &&, || all fail to parse — everything is a function: ADD(a,b), SUBTRACT(a,b), MULTIPLY(a,b), DIVIDE(a,b), GTE(a,b), LTE(a,b), EQUAL(a,b), AND(a,b), OR(a,b). A minus sign is only ever a negative number.
References
| Reference | Meaning |
|---|---|
{field} | A field on the current record. |
{ref.prop} | A field on the record a ref points at. Chains work: {shift.location.name}. |
{_THISRECORD.field} | Inside a query condition: the outer record, rather than the row being tested. |
{_THISUser.field} | The signed-in user. |
{_FORM.field} | A value entered in a form_action dialog. |
{_PREVROW.field}, {_NEXTROW.field}, {_INDEX}, {_TOTAL} | Position within a list pass. |
Quoting
Inside a formula string, write string literals with ordinary double quotes; in JSON that is one level of escaping: "expression": "DATEDIFF({start},{end},\"days\")". Don't escape twice — the formula language has no escape syntax of its own.
The condition argument of FILTER, COLLECTIONSELECT, EXISTS, SELECT and ORDERBY (and the extraCondition of REF_ROWS) is best written as a plain inline expression: EXISTS("cartitem", EQUAL({product},{_THISRECORD.product})). The older form, where the condition is passed as a quoted string, still works but can't contain its own string literals. Collection names, returnColumn, lookupColumn, sortField and foreignKey are always string literals, never field references. Leave the condition out entirely when there isn't one.
Function library
Where a parameter lists fixed values (like unit), they're literals — "day" instead of "days" silently does nothing.
Collections
| Function | Description |
|---|---|
EXISTS(collection, condition?) | True if any record matches. |
FILTER(collection, condition) | Matching records. |
COLLECTIONSELECT(collection, condition) | Matching records, including their computed fields. |
REF_ROWS(collection, foreignKey, extraCondition?) | Every record in collection whose foreignKey ref points back at this record. Shorthand for COLLECTIONSELECT(collection, EQUAL({foreignKey},{_THISRECORD.id})). |
SELECT(collection, returnColumn, condition?) | An array of one column's values. |
ORDERBY(collection, returnColumn, condition?, sortField?) | Like SELECT, sorted ascending. |
ORDERBYDESCENDING(collection, returnColumn, condition?, sortField?) | Like SELECT, sorted descending. |
LOOKUP(value, collection, lookupColumn, returnColumn) | A single value looked up across a collection. |
IN(value, list) | True if the value is in the array. |
COUNT(array) | Number of items. |
FIRST(array), LAST(array) | First or last element. |
SUMARRAY(array) | Sum of the numbers in an array. |
HERE() | The device's current location (client-side only — use in initialValue). |
USERPROFILE(field) | A field from the signed-in user's profile record. |
Logic
| Function | Description |
|---|---|
IF(condition, then, else) | Conditional. |
IFS(cond1, val1, cond2, val2, …, default) | The first true condition's value wins; a trailing unpaired argument is the default. |
AND(…), OR(…), NOT(a) | Boolean logic. |
EQUAL(a, b) | Equality. |
GT(a, b), LT(a, b), GTE(a, b), LTE(a, b) | Number comparison. Not for dates — use ISBEFORE / ISAFTER / ISBETWEEN. |
ISBLANK(value) | True for null, undefined, or an empty string. |
ROLE(name) | Validates a role name against the app's configured roles, returning it if valid and null if not — catches typos. Compare with it: EQUAL(USERPROFILE("role"), ROLE("admin")). |
Text
| Function | Description |
|---|---|
CONCATENATE(…) | Joins values (or a single array) into one string. |
JOIN(separator, …) | Joins values (or a single array) with a separator. |
UPPER(v), LOWER(v), TRIM(v) | Case and whitespace. |
LEN(v) | Length of a string or array. |
LEFT(v, n), RIGHT(v, n) | First or last N characters. |
CONTAINS(v, search) | True if the string contains the substring. |
REPLACE(v, search, replacement) | Replaces every occurrence. |
Math
| Function | Description |
|---|---|
ADD(a, b, …), SUBTRACT(a, b), MULTIPLY(a, b, …), DIVIDE(a, b) | Arithmetic. DIVIDE returns null on division by zero. |
MOD(n, divisor), POWER(base, exp), SQRT(v), ABS(v) | Remainder, power, square root, absolute value. |
ROUND(v, decimals) | Rounds to N decimal places. |
MIN(…), MAX(…), AVERAGE(…) | Pass an array (from SELECT, say) or separate values. |
DISTANCEBETWEEN(a, b, unit?) | Great-circle distance between two geolocation values. unit: meters (default) or km. |
Dates and times
For date and datetime comparisons always use ISBEFORE, ISAFTER and ISBETWEEN.
| Function | Description |
|---|---|
NOW(), TODAY(), YESTERDAY(), TOMORROW(), TIMENOW() | The current moment, or today/yesterday/tomorrow at midnight, or the current time. |
DATE(year, month, day, time?) | Builds a date. month is 1-based; time is "HH:mm" or "HH:mm:ss". |
TIME(value, date?) | Resolves an HH:mm(:ss) string against today or a given date. |
DATEADD(date, n, unit) | Adds a duration. unit: seconds, minutes, hours, days, weeks, months, years. |
DATEDIFF(a, b, unit) | Difference between two dates, in the same units. |
DATEFORMAT(date, format) | format: long, short, month, iso. |
DAYOFWEEK(day) | The date of a weekday this week (sunday … saturday, lowercase). |
YEAR(d), MONTH(d), DAY(d), HOUR(d), MINUTE(d), WEEKDAY(d) | Date parts. WEEKDAY is 0 (Sunday) to 6. |
STARTOFDAY(d?), ENDOFDAY(d?), STARTOFYEAR(d?), ENDOFYEAR(d?), STARTOFMONTH(), ENDOFMONTH() | Period boundaries (default: now). |
ISBEFORE(a, b), ISAFTER(a, b), ISBETWEEN(d, start, end) | Date comparisons (ISBETWEEN is inclusive). |
Generating values
These re-roll every time they are evaluated, so use them in initialValue (evaluated once when the create form opens) — never in a computed expression, where the value would keep changing.
| Function | Description |
|---|---|
RAND(min?, max?) | A random number from 0 up to (not including) 1 — or, with both arguments, a random whole number between them, inclusive. RAND(1000, 9999) is a random 4-digit number. |
UNIQUEID() | A fresh globally unique id (UUID v4). |
UNIQUECHAR(type, length) | A random string. type: letters, numeric, alphanumeric, special, or all (letters, numbers and special characters together). length: a whole number from 1 to 64. Returns blank for an unknown type or bad length. Random, not guaranteed unique — 4 alphanumeric characters give about 1.7 million combinations, so collisions become likely after a few thousand records. Use UNIQUEID() when a value must never repeat. |
json
{ "key": "booking_code", "label": "Booking code", "type": "text",
"readOnly": true, "initialValue": "UNIQUECHAR(\"alphanumeric\", 6)" }Rules of thumb
- Every
ref/multireftypeOptions.collectionmust name a collection that exists. - Every
fielditem in a view must exist in the collection'sschema, and everyactionitem in itsactions. defaultViewmust match a view name, and should almost never be adetailview.- Reverse relationships come in pairs: a
completeliston one collection (with aREF_ROWSformula) and arefon the other — add both halves together. - Keep formulas to the functions listed above; don't invent new ones.
- Prefer a simple schema that works over an exhaustive one.
A complete example
A small visits log: a patients collection, and a visits collection with a reference, a multi-select, and a questionnaire view.
json
[
{
"name": "patients",
"label": "Patients",
"icon": "person",
"order": 1,
"schema": [
{ "key": "full_name", "label": "Full name", "type": "text", "required": true, "isLabel": true },
{ "key": "phone", "label": "Phone", "type": "phone" },
{ "key": "visits", "label": "Visits", "type": "completelist",
"typeOptions": { "collection": "visits", "columns": ["visit_date", "conditions"] },
"computed": { "enabled": true, "expression": "REF_ROWS(\"visits\", \"patient\")" } }
],
"actions": [
{ "key": "delete", "label": "Delete", "icon": "delete", "type": "data", "isSystem": true,
"needsConfirmation": true, "actionConfig": { "type": "delete" } },
{ "key": "edit", "label": "Edit", "icon": "edit", "type": "app", "isSystem": true,
"actionConfig": { "type": "navigate_edit" } },
{ "key": "create", "label": "New", "icon": "add", "type": "app", "isSystem": true,
"actionConfig": { "type": "navigate_create" } }
],
"views": [
{ "name": "table", "type": "table",
"sections": [ { "order": 1, "items": [
{ "order": 1, "type": "field", "key": "full_name" },
{ "order": 2, "type": "field", "key": "phone" }
] } ] },
{ "name": "detail", "type": "detail",
"sections": [ { "order": 1, "label": "Patient", "items": [
{ "order": 1, "type": "field", "key": "full_name" },
{ "order": 2, "type": "field", "key": "phone" },
{ "order": 3, "type": "field", "key": "visits" },
{ "order": 4, "type": "action", "key": "edit" },
{ "order": 5, "type": "action", "key": "delete" }
] } ] }
],
"defaultView": "table"
},
{
"name": "visits",
"label": "Visits",
"icon": "medical_services",
"order": 2,
"schema": [
{ "key": "patient", "label": "Patient", "type": "ref", "required": true,
"description": "Which patient was seen?",
"typeOptions": { "collection": "patients", "displayField": "full_name" } },
{ "key": "visit_date", "label": "Visit date", "type": "date", "required": true,
"description": "When did the visit take place?", "initialValue": "TODAY()" },
{ "key": "conditions", "label": "Conditions", "type": "multienum",
"description": "Tick every condition that applies",
"typeOptions": { "values": [
{ "value": "fever", "label": "Fever" },
{ "value": "cough", "label": "Cough" },
{ "value": "headache", "label": "Headache" }
] } },
{ "key": "reference", "label": "Reference", "type": "text", "readOnly": true,
"initialValue": "UNIQUECHAR(\"alphanumeric\", 6)" }
],
"actions": [
{ "key": "delete", "label": "Delete", "icon": "delete", "type": "data", "isSystem": true,
"needsConfirmation": true, "actionConfig": { "type": "delete" } },
{ "key": "edit", "label": "Edit", "icon": "edit", "type": "app", "isSystem": true,
"actionConfig": { "type": "navigate_edit" } },
{ "key": "create", "label": "New", "icon": "add", "type": "app", "isSystem": true,
"actionConfig": { "type": "navigate_create" } }
],
"views": [
{ "name": "intake", "type": "questionnaire",
"sections": [
{ "order": 1, "label": "Who and when", "items": [
{ "order": 1, "type": "field", "key": "patient" },
{ "order": 2, "type": "field", "key": "visit_date" }
] },
{ "order": 2, "label": "Symptoms", "items": [
{ "order": 1, "type": "field", "key": "conditions" }
] }
],
"listFields": [
{ "order": 1, "type": "field", "key": "patient" },
{ "order": 2, "type": "field", "key": "visit_date" }
] },
{ "name": "detail", "type": "detail",
"sections": [ { "order": 1, "label": "Visit", "items": [
{ "order": 1, "type": "field", "key": "patient" },
{ "order": 2, "type": "field", "key": "visit_date" },
{ "order": 3, "type": "field", "key": "conditions" },
{ "order": 4, "type": "field", "key": "reference" },
{ "order": 5, "type": "action", "key": "edit" },
{ "order": 6, "type": "action", "key": "delete" }
] } ] }
],
"defaultView": "intake"
}
]