Skip to main content

How to Create Holding Confirmations and Payroll Statements using templates?

Generate stakeholder-level documents for equity holdings and payroll using customisable Word templates with variables in Ledgy.

Frances Agoncillo avatar
Written by Frances Agoncillo
Updated over a week ago

Introduction

Holding confirmations and payroll statements are stakeholder-level documents that provide an annual summary of a stakeholder's equity holdings. Both use the same template-based approach in Ledgy — the key difference is which data they loop through:

  • Holding Confirmations — summarise a stakeholder's stock (and optionally convertible) holdings, typically for investor confirmations or tax annexes.

  • Payroll Statements or Salary Annexes — summarise a stakeholder's grants and equity settlements, typically for employee payroll annexes or tax statements.

Both document types use the same templating engine: you create a .docx template with variables, upload it to Ledgy, and generate documents per stakeholder.


Step-by-step guide

Step 1: Create your template

Create a Word document (.docx) and add the variables listed below. You can also download Ledgy's example templates:

Step 2: Upload the template

  • Go to Documents > Templates > Upload Template

  • Upload the .docx file into the Template File box

  • Name your template and click Add template

Step 3: Generate the document

  • Go to Documents > Templates > Create from template

  • Select the date (all data up until this date will be used)

  • Select your template

  • Add the stakeholders (individually or by Group)

  • Optionally tick the checkbox to share with stakeholders immediately

  • Click Create


Variables reference

How variables work

Variables are placeholders in your .docx template that Ledgy automatically replaces with real data when generating documents. They are written in curly braces, e.g. {stakeholder.name}.

There are three types:

  • Global variables — work anywhere in the template

  • Stakeholder variables — work anywhere in the template; pull data from the stakeholder's profile

  • Looping (array) variables — work only inside a looping block like {#stakeholder.stocks}...{/stakeholder.stocks}; pull data from each individual transaction row


Global variables

These work anywhere in your template.

  • {today} — Today's date (the date the document is generated)

  • {date} — The date you selected in the generation form

  • {currency} — The currency set in Company Settings


Stakeholder variables

These work anywhere in your template. They pull data from the stakeholder's profile.

Personal details

  • {stakeholder.name} — The stakeholder's full name

  • {stakeholder.email} — The stakeholder's email address

  • {stakeholder.nationality} — The stakeholder's nationality

  • {stakeholder.birthdate} — The stakeholder's date of birth

  • {stakeholder.notes} — Any notes stored on the stakeholder's profile

  • {stakeholder.identifier} — The stakeholder's unique identifier (e.g. national ID, passport number, or company registration number)

Address

  • {stakeholder.address.line1} — First line of the stakeholder's address

  • {stakeholder.address.line2} — Second line of the stakeholder's address (e.g. apartment, suite number)

  • {stakeholder.address.postcode} — Postal/ZIP code

  • {stakeholder.address.city} — City

  • {stakeholder.address.county} — County, state, or region

Stakeholder custom fields

  • {stakeholder.X} — where X is the name of your custom stakeholder field

  • Example: If you have a custom field called "Cost Center" with value "7237-234", then {stakeholder.Cost Center}7237-234


Holding totals (outside looping blocks)

These variables work anywhere in your template — inside or outside looping blocks — and give aggregate totals for the stakeholder. They work for both Holding Confirmations and Payroll Statements, so use whichever ones are relevant to your template.

  • {stakeholder.issued} — Total number of shares issued (directly held) by the stakeholder

  • {stakeholder.granted} — Total number of instruments (options, phantoms, etc.) granted to the stakeholder

  • {stakeholder.stockVested} — Total number of vested shares the stakeholder holds

  • {stakeholder.grantVested} — Total number of vested instruments across all grants

  • {stakeholder.stockValue} — Total value of the stakeholder's stock holdings (Diluted shares × Latest share price)

  • {stakeholder.grantValue} — Total current value of all grants

  • {stakeholder.vestedStockValue} — Total value of vested stock

  • {stakeholder.vestedGrantValue} — Total value of vested grants

  • {stakeholder.grantNetValue} — Total net value of all grants

  • {stakeholder.ownershipPercentage} — The stakeholder's ownership percentage of the company

  • {stakeholder.votingPercentage} — The stakeholder's voting rights percentage

  • {stakeholder.shareCapital} — Total share capital (Issued shares × Nominal share price)

  • {stakeholder.dilutedShareCapital} — Total diluted share capital (Issued shares × Latest share price)


Stock variables

Use these inside the {#stakeholder.stocks}...{/stakeholder.stocks} looping block. Each row in the generated table represents one share class held by the stakeholder.

Structure in your template

Share Class

Issued

Nominal Share Price ({currency})

Stock Value ({currency})

{#stakeholder.stocks} {class}

{issued}

{nominalSharePrice}

{stockValue}{/stakeholder.stocks}

Variables inside the stocks loop

  • {issued} — Number of shares issued to the stakeholder in this share class

  • {investment} — Total investment amount (Share price paid × Number of shares at issuance)

  • {stockValue} — Current value of the stock holding (Diluted shares × Latest share price)

  • {class} — Name of the share class

  • {nominalSharePrice} — The nominal (par) share price for this share class

  • {shareCapital} — Share capital for this holding (Issued shares × Nominal share price)

  • {dilutedShareCapital} — Diluted share capital (Issued shares × Latest share price)

  • {stockVested} — Number of vested shares in this share class


Convertible variables

Use these inside the {#stakeholder.convertibles}...{/stakeholder.convertibles} looping block. Each row represents one convertible instrument.

Structure in your template

Date

Investment ({currency})

Cap ({currency})

Discount

Interest

{#stakeholder.convertibles} {date}

{investment}

{cap}

{discount}

{interest}{/stakeholder.convertibles}

Variables inside the convertibles loop

  • {date} — Date the convertible was issued

  • {investment} — Amount invested in the convertible loan

  • {cap} — Valuation cap of the convertible

  • {discount} — Discount rate applied upon conversion

  • {interest} — Interest rate on the convertible loan


Grant variables

Use these inside the {#stakeholder.grants}...{/stakeholder.grants} looping block. Each row represents one active grant the stakeholder holds.

Structure in your template

Grant Date

Type

Granted

Outstanding

Exercise Price ({currency})

Vesting

{#stakeholder.grants}{date}

{grantType}

{granted}

{outstanding}

{strikePrice}

{vesting}{/stakeholder.grants}

Variables inside the grants loop

  • {grantType} — Type of grant (e.g. Stock Option, Phantom, Warrant, RSU)

  • {poolName} — Name of the equity pool the grant was issued from

  • {granted} — Number of instruments granted

  • {grantValue} — Current value of this grant

  • {grantVested} — Number of instruments that have vested in this grant

  • {outstanding} — Number of instruments still outstanding (not yet exercised or settled)

  • {class} — Share class associated with this grant

  • {date} — Date the grant was made

  • {strikePrice} — Exercise/strike price per instrument

  • {vesting} — Vesting schedule summary text

  • {vesting.StartDate} — Start date of the vesting schedule

  • {shareCapital} — Share capital value for this grant

  • {dilutedShareCapital} — Diluted share capital value for this grant

  • {equityPlanName} — Name of the equity plan this grant belongs to

  • {expiryDate} — Expiry date of the grant

  • {grantNetValue} — Net value of the grant

  • {securityType} — Security type of the grant


Settlement variables

Use these inside the {#stakeholder.settlements}...{/stakeholder.settlements} looping block. Each row represents one equity settlement (exercise) transaction.

Structure in your template

Settled Date

Grant Date

Amount Exercised

Fair Market Value

({currency})

Exercise price

({currency})

Total Fair Market Value ({currency})

Total Taxable Gain ({currency})

{#stakeholder.settlements}{date}

{grantDate}

{exercised}

{fmvAtExercise}

{exercisePrice}

{totalFmvAtExercise}

{totalGainLoss}{/stakeholder.settlements}

Variables inside the settlements loop

  • {date} — Date the settlement/exercise occurred

  • {grantDate} — Date of the original grant that was exercised

  • {exercised} — Number of instruments exercised in this settlement

  • {fmvAtExercise} — Fair market value per share at the time of exercise

  • {exercisePrice} — Price paid per instrument to exercise

  • {totalFmvAtExercise} — Total fair market value at exercise (FMV × Number exercised)

  • {totalGainLoss} — Total gain or loss from the exercise ((FMV − Exercise price) × Number exercised)

  • {totalStrikePrice} — Total strike price paid (Exercise price × Number exercised)


Transaction custom field variables

Transaction custom fields let you add your own data points to transactions (e.g. "Tax Treatment", "Board Approval Status"). You can then pull those values into your templates.

Setup: Go to Company Settings > Data Management > Transaction custom fields to create custom fields.

Syntax: {customField.X} — where X is the exact name of your custom field.

Example: If you have a custom field named "Board approval status", use {customField.Board approval status} → Result: "Approved"

⚠️ Important: Transaction custom field variables only work inside looping blocks ({#stakeholder.grants}...{/stakeholder.grants}, {#stakeholder.stocks}...{/stakeholder.stocks}, {#stakeholder.settlements}...{/stakeholder.settlements}, or {#stakeholder.convertibles}...{/stakeholder.convertibles}). They cannot be used outside of these loops because they are tied to individual transactions, not to the stakeholder as a whole.

Example — using a custom field inside the grants loop

Share Class

Issued

Tax Value ({currency})

{#stakeholder.stocks} {class}

{issued}

{customField.Tax Value}{/stakeholder.stocks}

How values are resolved: When transactions are grouped (e.g. multiple transactions under the same grant), the custom field value is taken from the first transaction in the sequence.

See Custom fields for transactions for setup instructions.


Conditional display variables

Use these to show or hide entire sections of your template based on whether a stakeholder has certain types of holdings. Wrap the content you want to conditionally show between the opening tag and {/}.

  • {#stakeholder.hasStocks}...{/} — Only shows the enclosed content if the stakeholder holds shares

  • {#stakeholder.hasConvertibles}...{/} — Only shows if the stakeholder has convertible instruments

  • {#stakeholder.hasGrants}...{/} — Only shows if the stakeholder has active grants

  • {#stakeholder.hasSettlements}...{/} — Only shows if the stakeholder has equity settlements


FAQs

What is the difference between a Holding Confirmation and a Payroll Statement?

Both are stakeholder-level documents generated from templates. The difference is which looping block you use in your template:

  • Holding Confirmations use {#stakeholder.stocks} (and optionally {#stakeholder.convertibles}) to loop through share holdings — typically used for investors.

  • Payroll Statements use {#stakeholder.grants} and {#stakeholder.settlements} to loop through grants and equity exercises — typically used for employees.

You can combine both in a single template if needed.

Can I use stakeholder variables and totals outside of looping blocks?

Yes. Stakeholder variables (like {stakeholder.name}, {stakeholder.email}) and holding totals (like {stakeholder.grantValue}, {stakeholder.stockValue}) work anywhere in the template — inside or outside looping blocks.

Only looping variables (like {issued}, {granted}, {date} within arrays) and transaction custom field variables ({customField.X}) must be used inside their respective looping blocks.

What happened to the built-in Holding Confirmations feature?

Ledgy previously offered a built-in Holding Confirmations feature that generated documents automatically without requiring a custom template. This feature has since been deprecated and replaced by the more flexible template-based approach described in this article.

As a result of this deprecation, some variables that were part of the old built-in feature — such as the Tax Value variable — are no longer available.

How can I include tax value information in my templates now?

Since the Tax Value variable from the old built-in feature is no longer available, the recommended workaround is to use a transaction custom field:

Step 1 — Create a custom field: Go to Company Settings > Data Management > Transaction custom fields and create a new field (e.g. name it "Tax Value").

Step 2 — Populate the values: For each stakeholder's relevant transactions, manually enter the tax value in the custom field. You can do this:

  • One at a time: Open each transaction on the Transactions page and fill in the custom field value

  • In bulk: Use Ownership > Transactions > Bulk Edit, download the spreadsheet, fill in the custom field column, and re-upload

Step 3 — Add the variable to your template: Use {customField.Tax Value} inside the relevant looping block in your template.

Example — showing tax value in a grants table

{#stakeholder.grants}
| {grantType} | {granted} | {grantValue} | {customField.Tax Value} |
{/stakeholder.grants}

⚠️ Important: Transaction custom field variables like {customField.Tax Value} only work inside looping blocks — they cannot be placed outside of {#stakeholder.grants}...{/stakeholder.grants} or other array loops. This is because custom fields are attached to individual transactions, not the stakeholder overall.

Where do I set up custom fields?

Go to Company Settings > Data Management > Transaction custom fields. See our dedicated article: Custom fields for transactions.

Need further support? Please feel free to reach out to our Support team via chat or email.

Example templates

Did this answer your question?