Skip to content

Approval component schema

The approval component turns part of a form into an approval step. It identifies authorised approvers, stores the decision and audit details, can contain fields completed by the approver, and can send action-specific email notifications.

Do not add an approvalStatus component yourself. Team Forms derives the status value for each approval and the overall workflow metadata at runtime.

{
"type": "approval",
"key": "managerApproval",
"label": "Manager approval",
"hideLabel": true,
"components": [],
"approvers": [
{
"id": "existing-directory-object-id",
"displayName": "Alex Manager",
"mail": "alex.manager@example.com"
}
],
"chooseApprover": false,
"revokers": [],
"requestEmailTemplate": { "enabled": false },
"approvalEmailTemplate": { "enabled": false },
"rejectionEmailTemplate": { "enabled": false },
"revokeEmailTemplate": { "enabled": false }
}

approvers must contain exact existing directory user objects with id, displayName, and mail. Never invent IDs or use names as IDs. The AI assistant does not currently have a directory-search tool, so it may only reuse approvers already present in the form or values explicitly supplied by the user. Otherwise the approvers must be selected in the component editor.

PropertyTypeBehaviour
keystringUnique response-data key for this approval step.
labelstringHeading displayed for the approval block.
componentscomponent arrayOptional fields completed as part of the approval step. Their answers are nested under the approval key.
approversuser object arrayUsers allowed to approve or reject this step. Each object needs id, displayName, and mail.
chooseApproverbooleanWhen more than one approver exists, lets the requester select one. When false, all configured approvers are notified and any one may act.
revokersuser object arrayAdditional users allowed to revoke a decision. Uses the same user-object shape as approvers.
dependsOnstringFull response-data path of an earlier approval that must be approved first.
customConditionalJavaScript stringMakes the approval conditional by assigning a boolean to show.
collapsiblebooleanMakes the approval block collapsible.
collapsedIfEmptybooleanStarts an empty collapsible block collapsed.
expandForApproverbooleanExpands a collapsible block for its approver.
showApproversbooleanShows configured approvers in the block header before a request is made.
requestLabelstringReplaces the Request Approval button label.
approveLabelstringReplaces the Approve button label.
rejectLabelstringReplaces the Reject button label.
revokeLabelstringReplaces the Revoke button label.

The stored decision is available at data.<approvalKey>.approval. For example, data.managerApproval.approval.status is requested, approved, or rejected while that state is active. Team Forms also records the timestamp, requester, notified approvers, reviewer, and last actor as appropriate.

Approvals without dependsOn can be requested in parallel. To make a second top-level approval wait for the first, set its dependency to the first component’s key:

{
"type": "approval",
"key": "financeApproval",
"label": "Finance approval",
"components": [],
"approvers": [
{
"id": "existing-finance-user-id",
"displayName": "Finance Approver",
"mail": "finance.approver@example.com"
}
],
"dependsOn": "managerApproval"
}

dependsOn is the full data path, not a component ID or label. If an approval is inside an input container, include the container key, for example review.managerApproval. Layout-only parents such as panels do not add a path segment. Dependencies must refer to an earlier approval and must not form a cycle.

Use the standard executable conditional property:

{
"customConditional": "show = Number(data.totalExpense) > 1000"
}

Keep the normal submit button in a standard form. When an approval is visible, Team Forms automatically hides the submit button and shows the applicable Request, Approve/Reject, or Revoke actions. If every conditional approval is hidden, the normal submit button remains available. Wizards similarly hide their generated final submit action while an approval is visible.

The special managed revoker below resolves to the response’s original creator at runtime:

{
"id": "creator",
"userPrincipalName": "Original Creator",
"displayName": "Original Creator",
"mail": "The original creator of this response",
"givenName": "Original",
"surname": "Creator",
"jobTitle": "",
"userLookupId": "creator"
}

Each action has an independent wrapper: requestEmailTemplate, approvalEmailTemplate, rejectionEmailTemplate, and revokeEmailTemplate.

While authoring, an enabled wrapper contains an email template in value:

{
"requestEmailTemplate": {
"enabled": true,
"value": {
"to": "{{ notifiedApprovers }}",
"cc": "{{ requester.mail }}",
"subject": "Approval requested - {{ title }}",
"body": "{{ requester.displayName }} requested your approval.\n\n{{{ editUrl }}}",
"saveToSentItems": true,
"attachments": [
{
"name": "{{ title }}.pdf",
"contentType": "application/pdf",
"contentBytes": "{{{ pdf }}}"
}
]
}
}
}

Published schemas may replace value with a stored template hash; preserve an existing hash unless replacing that notification template intentionally. All dynamic email values use Handlebars, not JavaScript. See Email template syntax for the available helpers and common response fields.

Approval templates additionally receive:

ValueAvailable for
requester.displayName, requester.mailAll approval actions
notifiedApproversRequest notifications; renders the selected or notified email addresses
reviewer.displayName, reviewer.mailApproval and rejection notifications
revoker.displayName, revoker.mailRevoke notifications
revokersConfigured revoker objects; iterate with #each when needed