Skip to content

Template Fields

Fields define what information users enter when creating a matter. Each field has a type that determines how it’s displayed and validated.

Every field is an object inside its block’s fields array:

{
"key": "client.given_names",
"label": "Given Names",
"type": "text",
"required": true,
"help_text": "Optional help text shown below the field"
}
PropertyRequiredDescription
keyYesDot-notation field key (e.g. client.surname). The same key is used in document placeholders ({{ client.surname }}).
typeYesThe field type (see below)
labelNoLabel shown to users. Defaults to a humanised version of the key.
requiredNoWhether the field must be filled (default: false)
default_valueNoInitial value pre-filled into the field
placeholderNoPlaceholder text shown in an empty input
help_textNoExplanatory text shown below the field
optionsNoArray of choices (required for select / radio)
validationNoObject with pattern, min_length, max_length, min, max
visible_whenNoCondition expression — see Conditionals
computed_fromNoFormula to auto-calculate the value from other fields
quick_entryNoShow in Quick Entry mode (default: false)
reference_keyNoFor reference fields — the source key to mirror
widthNo"full" (default), "half", or "third" for column layouts

A single-line text input. Use for names, references, and short text.

{
"key": "client.given_names",
"label": "Given Names",
"type": "text",
"required": true
}

In documents: {{ client.given_names }}

A multi-line text area. Use for addresses, notes, or longer text. Always renders full-width.

{
"key": "matter.notes",
"label": "File Notes",
"type": "textarea"
}

In documents: {{ matter.notes }}

A date picker. Stores dates in ISO format (YYYY-MM-DD).

{
"key": "client.date_of_birth",
"label": "Date of Birth",
"type": "date"
}

In documents:

  • Raw: {{ client.date_of_birth }} → “2026-01-15”
  • Formatted: {{ client.date_of_birth | date("%-d %B %Y") }} → “15 January 2026”

A number input formatted as currency.

{
"key": "matter.purchase_price",
"label": "Purchase Price",
"type": "currency",
"required": true
}

In documents: {{ matter.purchase_price | currency }} → “$150,000.00”. Raw values render as the stored number, so use the currency filter for AUD formatting.

A numeric input (no currency formatting).

{
"key": "estate.number_of_beneficiaries",
"label": "Number of Beneficiaries",
"type": "number"
}

In documents: {{ estate.number_of_beneficiaries }}

A phone number input with format validation.

{
"key": "client.phone",
"label": "Phone Number",
"type": "phone"
}

In documents: {{ client.phone }}

An email address input with validation.

{
"key": "client.email",
"label": "Email Address",
"type": "email"
}

In documents: {{ client.email }}

A dropdown menu with predefined options.

{
"key": "client.state",
"label": "State",
"type": "select",
"options": ["NSW", "VIC", "QLD", "SA", "WA", "TAS", "NT", "ACT"],
"required": true
}

In documents: {{ client.state }}

A set of mutually exclusive radio buttons. Like select, requires an options array.

{
"key": "matter.urgency",
"label": "Urgency",
"type": "radio",
"options": ["Standard", "Urgent", "Emergency"]
}

A single standalone checkbox. For yes/no fields wired into document conditionals, prefer bool (which the rest of the engine and inverse pipeline understands).

A yes/no toggle. Stored as the strings "true" or "false".

{
"key": "estate.has_will",
"label": "Deceased had a Will",
"type": "bool"
}

A read-only mirror of another field. See the Reference Fields section below.

Controls field width for multi-column layouts. When multiple fields share the same row, narrower widths let them sit side by side.

ValueWidthUse for
"full"100% (default)Addresses, notes, long text
"half"50%Names, dates, phone numbers
"third"33%State, postcode, short codes
"fields": [
{
"key": "client.given_names",
"label": "Given Names",
"type": "text",
"width": "half"
},
{
"key": "client.surname",
"label": "Surname",
"type": "text",
"width": "half"
}
]

Mark a field with "quick_entry": true to include it in the Quick Entry panel. Quick Entry mode presents only the most essential fields so users can capture key information fast and fill in remaining details later.

{
"key": "client.surname",
"type": "text",
"label": "Surname",
"required": true,
"quick_entry": true
}

Explanatory text shown below the field:

{
"key": "matter.re_line",
"label": "Re: Line",
"type": "text",
"help_text": "Brief description used in folder naming and correspondence"
}

Placeholder text shown in empty fields:

{
"key": "client.email",
"label": "Email",
"type": "email",
"placeholder": "[email protected]"
}

Initial value pre-filled in the field:

{
"key": "client.state",
"label": "State",
"type": "select",
"options": ["NSW", "VIC", "QLD", "SA", "WA", "TAS", "NT", "ACT"],
"default_value": "NSW"
}

Fields are organised into blocks:

{{ block_name.field_name }}

Common block names:

  • client — Client information
  • matter — Matter details
  • estate — Estate-specific (for Estates template)
  • property — Property details (for Conveyancing)

When an address is verified through Apple MapKit, Certum Draft emits these system-managed keys alongside the address parts. You don’t define them in matter.json, but they’re available in document templates:

KeyMeaning
<entity>.address_verified"true" if the address has been verified via MapKit
<entity>.address_verified_sourceVerification source (e.g. mapkit)
<entity>.address_verified_atISO timestamp of verification
<entity>.address_verified_fingerprintStable hash of the canonical parts

At render time, if the canonical structured parts (street, suburb, state, postcode) drift from what was verified, the engine emits an orange [DRIFT: ...] marker in the document so the lawyer can review before sending.

Boolean fields follow a standard naming pattern:

PrefixMeaningExample
is_*State or characteristicproperty.is_strata, sale.is_auction
has_*Presence of somethingproperty.has_pool, client.has_poa

For “if not” cases in documents, prefer the Jinja not operator over creating helper inverse fields:

{%p if not sale.is_auction %}
Private treaty terms...
{%p endif %}

The render engine blanks the string "false" to "" for all boolean values, which makes {% if x %} and {% if not x %} both behave correctly without relying on hand-built inverse fields. See Conditionals for the full guidance and the safety rules.

DoDon’t
client.full_nameclientFullName
matter.settlement_datesettlementDate
estate.deceased_namedeceased
property.is_stratastrata_yn
client.has_poapoa_exists

Use lowercase with underscores. Be descriptive but concise.

Reference fields display a read-only mirror of a field defined in another block. They’re perfect for creating “checklist” blocks that show all the data needed for a specific letter in one place.

{
"key": "ref.is_strata",
"label": "Property is Strata",
"type": "reference",
"reference_key": "property.is_strata"
}
PropertyRequiredDescription
typeYesMust be "reference"
labelYesLabel shown to users
reference_keyYesThe dot-notation key of the source field (e.g., "property.is_strata")

Reference fields:

  • Show the current value of the source field in real time
  • Display a Ref badge to distinguish them from editable fields
  • Render boolean values as disabled checkboxes for quick visual confirmation
  • Include a navigation arrow that jumps to the source block for editing
  • Should never be marked as required — they don’t represent data entry
  • Don’t affect completion tracking
{
"name": "Sending Contract Checklist",
"description": "Quick reference for the Letter to Client Sending Contract",
"workflow_stage": "contract",
"collapsed": true,
"fields": [
{ "key": "ref.is_strata", "label": "Property is Strata", "type": "reference", "reference_key": "property.is_strata" },
{ "key": "ref.swimming_pool", "label": "Has Swimming Pool", "type": "reference", "reference_key": "property.swimming_pool" },
{ "key": "ref.is_auction", "label": "Sale by Auction", "type": "reference", "reference_key": "sale.is_auction" },
{ "key": "ref.agency_name", "label": "Agent", "type": "reference", "reference_key": "agent.agency_name" }
]
}

Some fields are calculated from other fields using the computed_from property:

{
"key": "client.full_name",
"label": "Full Name",
"type": "text",
"computed_from": "{client.title} {client.given_names} {client.surname}"
}

The value is recalculated automatically whenever any of its source fields change (debounced ~150ms).

In addition to simple interpolation ({field1} {field2}), you can use these functions:

FunctionDescriptionExample
uppercase()Converts to uppercaseuppercase({client.surname})
lowercase()Converts to lowercaselowercase({client.email})
join_non_empty()Joins non-empty values with a separator (last quoted arg)join_non_empty({client.suburb}, {client.state}, {client.postcode}, " ")
choose()2-arg: choose({flag}, "text"). 3-arg: choose({flag}, "true", "false"). 4-arg: choose({field}, "match", "true", "false").choose({property.is_strata}, "Strata", "Torrens")
scale()Looks up a value in a named tiered fee schedule (declared under top-level scales)scale({purchase.price}, "nsw_transfer_duty")
multiply()Multiplies a field value by a constant factormultiply({purchase.price}, 0.1)
date_add()Adds days from one field to a date in another fielddate_add(matter.exchange_date, matter.settlement_period)
format_long_au()Formats an ISO date as “Friday, 4 May 2026”format_long_au(matter.settlement_date)
user_override_else()Returns the manual field if non-empty, otherwise the fallback expressionuser_override_else(transaction.settlement_date_manual, date_add(transaction.exchange_date, transaction.settlement_period))
{
"key": "purchase.deposit_amount",
"label": "Deposit (10%)",
"type": "currency",
"computed_from": "multiply({purchase.price}, 0.1)"
}
{
"key": "purchase.transfer_duty",
"label": "NSW Transfer Duty",
"type": "currency",
"computed_from": "scale({purchase.price}, nsw_transfer_duty)"
}
{
"key": "matter.settlement_date",
"label": "Settlement Date",
"type": "date",
"computed_from": "date_add(matter.exchange_date, matter.settlement_period)"
}

Certum Draft automatically provides these date variables in every template context — you do not need to define them as fields:

VariableFormatExample
today.dateFull date”6 April 2026”
today.date_longFull date (same as today.date)“6 April 2026”
today.date_shortShort date”06/04/2026”
today.date_isoISO format”2026-04-06”
today.dayDay of month”6”
today.monthMonth name”April”
today.yearYear only”2026”

Use them in document templates:

This letter is dated {{ today.date_long }}.

Common computed fields you’ll define yourself:

  • full_name — Combines title, given names, and surname
  • address_single_line — Combines street, suburb, state, postcode

Mark fields as required: true when:

  • The field is essential for most documents
  • Missing data would cause obvious problems

Mark fields as required: false when:

  • The field is only needed sometimes
  • Not all matters have this information
{
"name": "Client Details",
"workflow_stage": "Intake",
"fields": [
{
"key": "client.title",
"label": "Title",
"type": "select",
"options": ["Mr", "Mrs", "Ms", "Dr", "Prof"],
"width": "third"
},
{
"key": "client.given_names",
"label": "Given Names",
"type": "text",
"required": true,
"width": "half",
"quick_entry": true
},
{
"key": "client.surname",
"label": "Surname",
"type": "text",
"required": true,
"width": "half",
"quick_entry": true
},
{
"key": "client.full_name",
"label": "Full Name",
"type": "text",
"computed_from": "{client.title} {client.given_names} {client.surname}"
},
{
"key": "client.date_of_birth",
"label": "Date of Birth",
"type": "date"
},
{
"key": "client.street_address",
"label": "Street Address",
"type": "text",
"required": true
},
{
"key": "client.suburb",
"label": "Suburb",
"type": "text",
"required": true,
"width": "half"
},
{
"key": "client.state",
"label": "State",
"type": "select",
"options": ["NSW", "VIC", "QLD", "SA", "WA", "TAS", "NT", "ACT"],
"required": true,
"default_value": "NSW",
"width": "third"
},
{
"key": "client.postcode",
"label": "Postcode",
"type": "text",
"required": true,
"width": "third"
},
{
"key": "client.phone",
"label": "Phone",
"type": "phone"
},
{
"key": "client.email",
"label": "Email",
"type": "email"
}
]
}