Overview
Review Templates use Jinja templating to create dynamic, data-driven prompts for users during document review. When you set a data element's source to "Review," you provide a Jinja template that generates personalized guidance based on extracted data, external data, and document content.
What are Review Templates?
Review Templates are Jinja expressions that:
Guide users - Provide context-specific instructions during data review
Use extracted data - Reference data already extracted from the document
Access external data - Include information uploaded with the document
Display dynamically - Generate different prompts based on document content
Improve accuracy - Give reviewers the information they need to verify data
Example use case: You're reviewing invoices and want users to verify the total matches an external system. Your template displays: "Please verify the invoice total matches the expected amount of $1,234.56 from the billing system."
When to Use Review Data Source
Set a data element's data source to "Review" when:
Data requires human verification or correction
Users need context from external systems to validate data
The value should be manually entered rather than extracted
You want to guide users with dynamic instructions
Combining AI extraction with human oversight for critical fields
Configuring Review Templates in the UI
Steps
Open your Data Definition
Select or create a data element
Navigate to the Data Source tab
Set source to Review
Go to the Semantics tab
Enter your Jinja template in the text area
Save your changes
The Semantics Tab for Review
When data source is set to Review, the Semantics tab provides:
Large text area - Multi-line editor for your Jinja template
Variable access - Use content, family, data, externalData, metadata
Jinja syntax - Full Jinja templating capabilities
Preview capability - Test templates with sample data
Jinja Templating Basics
Jinja is a Python templating engine that lets you embed dynamic data in static text.
Core Syntax
1. Variables
Display variable values:
Hello, #{{ user_name }}!
2. Conditionals
Show content based on conditions:
{% if total > 1000 %}
High-value transaction - review carefully
{% else %}
Standard transaction
{% endif %}
3. Loops
Iterate over lists:
Line items to verify:
{% for item in items %}
- #{{ item.description }}: $#{{ item.amount }}
{% endfor %}
4. Filters
Transform values:
#{{ document_title | upper }}
#{{ price | round(2) }}
#{{ name | default('Unknown') }}
Common filters:
upper- Uppercase textlower- Lowercase texttitle- Title casedefault(value)- Fallback if variable is emptyround(precision)- Round numberslength- Count items in list
Available Variables
Review templates have access to these variables:
content
The full text content of the document.
Review the following content:
#{{ content }}
family
The document family object containing metadata and properties.
Document: #{{ family.name }}
Uploaded: #{{ family.createdOn }}
Status: #{{ family.status }}
data
List of data objects already extracted from the document. Access specific elements by name.
{% for obj in data %}
{% if obj.name == 'invoice_number' %}
Invoice #: #{{ obj.value }}
{% endif %}
{% endfor %}
externalData
External data uploaded with the document family (JSON object).
Expected total: $#{{ externalData.expected_amount }}
Customer: #{{ externalData.customer_name }}
PO Number: #{{ externalData.po_number }}
metadata
Document family metadata (filename, upload date, custom metadata).
File: #{{ metadata.filename }}
Uploaded by: #{{ metadata.uploader }}
Common Patterns
Verification Against External Data
Scenario: User must verify invoice total matches billing system
Please verify the invoice total matches the expected amount of $#{{ externalData.total_bill_amount }}
Contextual Instructions
Scenario: Different instructions based on document type
{% if metadata.document_type == 'invoice' %}
Verify all line items and totals
{% elif metadata.document_type == 'receipt' %}
Confirm payment method and amount
{% else %}
Review document for accuracy
{% endif %}
Displaying Extracted Data for Comparison
Scenario: Show what AI extracted so user can verify
AI extracted the following information:
{% for obj in data %}
#{{ obj.name }}: #{{ obj.value }}
{% endfor %}Please verify this matches the document.
Conditional Warnings
Scenario: Warn about high-value transactions
{% for obj in data %}
{% if obj.name == 'total_amount' and obj.value|float > 5000 %}
⚠️ HIGH-VALUE TRANSACTION - Extra verification required
{% endif %}
{% endfor %}
Multi-Item Review
Scenario: Guide user through multiple line items
Please verify each line item:
{% for item in externalData.line_items %}
#{{ loop.index }}. #{{ item.description }} - Qty: #{{ item.quantity }}, Price: $#{{ item.price }}
{% endfor %}Total should be: $#{{ externalData.expected_total }}
Advanced Techniques
Using Macros
Define reusable template components:
{% macro render_field(label, value) %}
#{{ label }}: #{{ value if value else 'Not found' }}
{% endmacro %}#{{ render_field('Invoice Number', invoice_number) }}
#{{ render_field('Date', invoice_date) }}
#{{ render_field('Amount', total_amount) }}
Accessing Nested Data
Navigate through complex data structures:
Customer: #{{ externalData.customer.name }}
Address: #{{ externalData.customer.address.street }}, #{{ externalData.customer.address.city }}
Contact: #{{ externalData.customer.contact.email }}
Safe Navigation
Handle missing data gracefully:
#{{ externalData.customer.name | default('Unknown Customer') }}
#{{ data[0].value if data else 'No data extracted yet' }}
Best Practices
Be specific - Give clear, actionable instructions
Provide context - Show users why they're reviewing this field
Use defaults - Handle missing data with
| default()filterFormat numbers - Use
| round(2)for currencyKeep it concise - Long templates overwhelm users
Test with sample data - Verify templates work with various inputs
Handle edge cases - Check for empty lists, null values
Use conditions wisely - Show relevant info only
Examples by Use Case
Invoice Verification
Please verify this invoice:Extracted Information:
- Invoice #: #{{ invoice_number }}
- Date: #{{ invoice_date }}
- Total: $#{{ total_amount }}Expected from billing system:
- PO Number: #{{ externalData.po_number }}
- Expected Total: $#{{ externalData.expected_amount }}{% if total_amount|float != externalData.expected_amount|float %}
⚠️ WARNING: Totals do not match!
{% endif %}
Contract Review
Review contract for #{{ externalData.client_name }}:Key terms to verify:
{% for term in externalData.key_terms %}
- #{{ term.name }}: #{{ term.value }}
{% endfor %}Confirm all signatures are present.
Expense Report
Employee: #{{ externalData.employee_name }}
Department: #{{ externalData.department }}Verify expenses against policy:
{% for expense in data %}
{% if expense.name == 'expense_amount' %}
{% if expense.value|float > 500 %}
⚠️ Requires manager approval (over $500)
{% endif %}
{% endif %}
{% endfor %}
Troubleshooting
Template Not Rendering
Check Jinja syntax for errors
Ensure variable names match exactly
Verify data source is set to "Review"
Test with simple template first
Variables Showing as Empty
Confirm external data was uploaded with document
Check variable names match external data structure
Use
| default('N/A')for optional fieldsVerify data elements have been extracted before Review element
Loops Not Working
Ensure you're iterating over a list
Check that the list exists and has items
Use
{% if items %}to check before loopingTest with
#{{ items | length }}to see count
Tips
Start with simple templates and add complexity gradually
Use comments in templates:
{# This is a comment #}Test templates with various document types
Combine Review with other data sources in the same definition
Use external data to provide context from other systems
Consider mobile users - keep templates readable on small screens
Document your templates for future maintainers
Review templates are evaluated when the review form loads
Changes to external data require re-opening the review form
