Documentation Index Fetch the complete documentation index at: https://docs.getveles.com/llms.txt
Use this file to discover all available pages before exploring further.
Veles generates branded proposals, order forms, and contracts directly from quote data. You build templates in Microsoft Word (DOCX) or Google Docs/Slides, insert merge fields that reference quote variables, and Veles renders the final document with live deal data at generation time.
Templates are managed by admins and available to reps when generating documents from a quote. The output reflects your brand identity (logo, colors) and can include pricing tables, terms, CRM data, and any content from the quote’s blocks.
Format Template Output Notes DOCX (Microsoft Word).docx file with merge fieldsPDF or DOCX Uses Word’s MERGEFIELD syntax. Most flexible for complex layouts. Google Docs Google Doc with template tags PDF or Google Doc Uses {{ }} handlebars syntax. Easier to collaborate on templates. Google Slides Google Slide deck with template tags PDF or Google Slides Same {{ }} syntax. Best for visual proposals and pitch decks.
Template syntax
DOCX (Word)
Google Docs / Slides
Inserting merge fields
Place your cursor where you want the dynamic value.
Press Ctrl+F9 (Windows) or Cmd+F9 (Mac) to create field brackets { }.
Type the MERGEFIELD syntax between the brackets.
Press Cmd+Shift+Option+U to save the merge field.
Use Alt+F9 (Windows) or Option+F9 (Mac) to toggle between field codes and rendered values.
Alternative: Insert → Quick Parts → Field → choose “MergeField” from the list.Syntax reference Operation Syntax Simple value MERGEFIELD =title \* MERGEFORMATNested value MERGEFIELD =owner.name \* MERGEFORMATLoop start MERGEFIELD options:each(option) \* MERGEFORMATLoop variable MERGEFIELD =option.name \* MERGEFORMATLoop end MERGEFIELD options:endEach \* MERGEFORMATConditional start MERGEFIELD salesforce:if \* MERGEFORMATConditional end MERGEFIELD salesforce:endIf \* MERGEFORMATBoolean conditional MERGEFIELD block:if(is_option) \* MERGEFORMAT
Syntax reference Google Docs and Google Slides use the same handlebars-style syntax. Operation Syntax Simple value {{ title }}Nested value {{ owner.name }}Loop start {{ #each(options) as option }}Loop variable {{ option.name }}Loop end {{ /each }}Conditional start {{ #if(salesforce) }}Else if {{ #elseif(primary_option) }}Else {{ #else }}Conditional end {{ /if }}
Template variables reference
Every variable below is available in all template formats. Use dot notation to access nested values (e.g., owner.name, line.formatted.price).
Top-level fields
Variable Type Description titleString The quote/opportunity title. logoImage Company logo from your brand settings . terms_htmlHTML Combined HTML from all Terms and Text blocks. Nullable. blocksArray All quote blocks in order (title, terms, options, text). See Blocks . optionsArray Pricing Option blocks only. See Options . primary_optionObject The primary option (nullable if none set). Same structure as an option.
Owner (sales rep)
Access via owner.*.
Variable Type Description Example owner.nameString Full name ”Michael Scott” owner.emailString Email address ”michael@company.com ” owner.phoneString Phone number ”(555) 123-4567” owner.job_titleString Job title ”Regional Manager”
Title block
Access via title_block.* or when iterating blocks with is_title.
Variable Type Description title_block.nameString Quote name. title_block.fromString From company name. title_block.prepared_byString Preparer name. title_block.prepared_by_extraString Preparer additional info (title, email). title_block.forString Recipient company name. title_block.for_extraString Recipient additional info. title_block.issued_onDate Issue date (e.g., “January 15, 2025”). title_block.valid_untilDate Expiry date.
Blocks
The blocks array contains all blocks in the quote, in display order. Since blocks are polymorphic (they can be different types), use the type flags to conditionally render content.
Flag True when is_titleTitle block (cover page data). is_termsTerms or aggregated terms block. is_optionPricing Option block. is_textText block (free-form content).
Each block also has terms_html (for Terms/Text blocks) and name (for Title/Option blocks).
Options
Access via the options array, primary_option, or when iterating blocks with is_option. Each option contains:
Variable Type Description Example option.nameString Option name. ”Enterprise Plan” option.frequencyString Billing frequency. ”annual”, “monthly”, “quarterly” option.year_countInteger Number of calculation periods. 3 option.formatted_contract_lengthString Human-readable contract length. ”3 years” option.total_valueString Raw decimal total. ”150000.00” option.formatted_total_valueCurrency Formatted total. ”$150,000.00” option.currencyString Currency code. ”USD” option.start_dateDate First calculation start. ”January 1, 2025” option.end_dateDate Last calculation end. ”December 31, 2027” option.service_start_dateDate Service start date (nullable). option.upliftString Annual uplift percentage (nullable). “3%“ option.custom_fieldsHash Option-level custom fields (dynamic keys). option.terms_htmlHTML Terms specific to this option (nullable). option.calculationsArray One per billing period. See Calculations .
Calculations (periods)
Each option contains a calculations array with one entry per billing period (year, quarter, month). Access via option.calculations.
Variable Type Description Example calc.yearInteger 1-based period number. 1 calc.currencyString Currency code. ”USD” calc.start_dateDate Period start. ”January 1, 2025” calc.end_dateDate Period end. ”December 31, 2025” calc.total_discountFloat Raw discount amount. 5000.0 calc.creditsString Formatted credits (abbreviated). “100K” calc.credits_fullString Full unscaled credits number. ”100000” calc.credit_rateCurrency Unit price per credit. calc.credit_discountString Discount on credits. calc.credit_totalCurrency Credits total formatted. calc.summaryHash Summary variables (dynamic keys). calc.uom_fieldsHash UOM field values (dynamic keys). {"seats": "100K"}calc.custom_columnsHash Custom calculation columns (dynamic keys). calc.any_one_timeBoolean Has one-time lines? calc.any_recurringBoolean Has recurring lines? calc.any_transactionalBoolean Has transactional lines? calc.linesArray All line items. See Line Items . calc.one_time_linesArray One-time lines only. calc.recurring_linesArray Recurring lines only.
Access via calc.formatted.*.
Variable Type Description Example calc.formatted.totalCurrency Period total. ”$50,000.00” calc.formatted.original_totalCurrency Pre-discount total. ”$55,000.00” calc.formatted.discountCurrency Discount amount. ”$5,000.00” calc.formatted.discount_totalCurrency Total discount formatted. calc.formatted.system_totalCurrency System-calculated total. calc.formatted.system_discountCurrency System-calculated discount.
One-time vs. recurring breakout
Access via calc.breakout.*. Both raw numbers and formatted strings are available.
Variable Type Description calc.breakout.one_time_originalFloat Raw one-time original amount. calc.breakout.one_time_totalFloat Raw one-time total. calc.breakout.recurring_originalFloat Raw recurring original amount. calc.breakout.recurring_totalFloat Raw recurring total. calc.breakout.formatted_one_time_originalCurrency One-time list price. calc.breakout.formatted_one_time_totalCurrency One-time net price. calc.breakout.formatted_recurring_originalCurrency Recurring list price. calc.breakout.formatted_recurring_totalCurrency Recurring net price. calc.breakout.formatted_one_time_listCurrency One-time list (alternate). calc.breakout.formatted_one_time_netCurrency One-time net (alternate). calc.breakout.formatted_recurring_listCurrency Recurring list (alternate). calc.breakout.formatted_recurring_netCurrency Recurring net (alternate).
Line items
Access via calc.lines, calc.one_time_lines, or calc.recurring_lines. Each line represents a single product on the quote.
Variable Type Description Example line.product_nameString Product display name. ”Enterprise License” line.product_skuString Product SKU (nullable). line.categoryString Product category (nullable). line.quantityString Quantity value. ”50” line.metric_valueString UOM + scale suffix. ”100K” line.unit_priceFloat Raw unit price. 100.0 line.one_timeBoolean Is this a one-time charge? line.is_transactionalBoolean Is this a transactional charge? line.proratedBoolean Is this prorated? line.custom_columnsHash Line-level custom columns (dynamic keys). line.product_custom_fieldsHash Product custom fields (dynamic keys).
Access via line.formatted.*. These are pre-formatted for display.
Variable Type Description Example line.formatted.nameString Display name. line.formatted.original_priceCurrency List price. ”$5,000.00” line.formatted.priceCurrency Net price. ”$4,500.00” line.formatted.discountCurrency Discount amount. ”$500.00” line.formatted.prorated_priceCurrency Prorated price (if applicable). line.formatted.unit_priceCurrency Formatted unit price. ”$100.00” line.formatted.system_priceCurrency System-calculated price. line.formatted.system_price_discountCurrency System price discount.
Unit of Measure
Access via line.uom.* (nullable — may not be present on all lines).
Variable Type Description Example line.uom.keyString UOM key. ”seats” line.uom.labelString UOM display label. ”Seats”
Salesforce data
Available when the quote is linked to Salesforce. Always wrap in a conditional since this is null when Salesforce is not connected.
Variable Type Description salesforce.account_nameString SF account name. salesforce.account_idString SF account ID. salesforce.account_phoneString Account phone. salesforce.account_websiteString Account website URL. salesforce.stageString Opportunity stage. salesforce.crm_urlString Link to Salesforce record. salesforce.cpq_urlString Link to Veles CPQ record. salesforce.last_syncString Last sync timestamp (ISO 8601). salesforce.custom_fields.*Dynamic Custom fields mapped in Veles. Access via dot notation: salesforce.custom_fields.my_field.
Addresses
Access via salesforce.billing_address.* or salesforce.shipping_address.* (both nullable).
Variable Type *.streetString *.cityString *.stateString *.postal_codeString *.countryString
Template examples
Cover page (DOCX)
«=title_block.name»
Prepared for: «=title_block.for»
«=title_block.for_extra»
Prepared by: «=title_block.prepared_by»
«=title_block.prepared_by_extra»
Date: «=title_block.issued_on»
Valid until: «=title_block.valid_until»
Iterating through all blocks (DOCX)
Use the type flags to render each block type differently:
«blocks:each(block)»
«block:if(is_title)»
«=block.name»
Prepared by: «=block.prepared_by»
«block:endIf»
«block:if(is_option)»
Option: «=block.name»
Total: «=block.formatted_total_value»
«block:endIf»
«block:if(is_terms)»
«=block.terms_html»
«block:endIf»
«block:if(is_text)»
«=block.terms_html»
«block:endIf»
«blocks:endEach»
Pricing options with year-by-year breakdown (DOCX)
«options:each(option)»
«=option.name» — «=option.formatted_contract_length»
Total Contract Value: «=option.formatted_total_value»
«option.calculations:each(calc)»
Year «=calc.year» («=calc.start_date» – «=calc.end_date»)
Total: «=calc.formatted.total»
«calc:if(any_one_time)»
One-Time Fees: «=calc.breakout.formatted_one_time_total»
«calc:endIf»
«calc:if(any_recurring)»
Recurring: «=calc.breakout.formatted_recurring_total»
«calc:endIf»
«option.calculations:endEach»
«options:endEach»
Line items table (DOCX)
«calc.lines:each(line)»
«=line.formatted.name» | «=line.quantity» | «=line.formatted.unit_price» | «=line.formatted.price»
«calc.lines:endEach»
Separate one-time and recurring tables (DOCX)
«calc:if(any_recurring)»
Recurring Charges:
«calc.recurring_lines:each(line)»
«=line.formatted.name» | «=line.quantity» | «=line.formatted.price»
«calc.recurring_lines:endEach»
Recurring Total: «=calc.breakout.formatted_recurring_total»
«calc:endIf»
«calc:if(any_one_time)»
One-Time Charges:
«calc.one_time_lines:each(line)»
«=line.formatted.name» | «=line.formatted.price»
«calc.one_time_lines:endEach»
One-Time Total: «=calc.breakout.formatted_one_time_total»
«calc:endIf»
Salesforce customer info with conditional (DOCX)
«salesforce:if»
Customer: «=salesforce.account_name»
«=salesforce.billing_address.street»
«=salesforce.billing_address.city», «=salesforce.billing_address.state» «=salesforce.billing_address.postal_code»
«salesforce:endIf»
Full proposal (Google Docs)
{{ title_block.name }}
Prepared for: {{ title_block.for }}
Prepared by: {{ title_block.prepared_by }}
Date: {{ title_block.issued_on }}
{{ #each(options) as option }}
Option: {{ option.name }}
Contract Length: {{ option.formatted_contract_length }}
Total: {{ option.formatted_total_value }}
{{ #each(option.calculations) as calc }}
Year {{ calc.year }}:
{{ #each(calc.lines) as line }}
- {{ line.formatted.name }}: {{ line.quantity }} × {{ line.formatted.unit_price }} = {{ line.formatted.price }}
{{ /each }}
Period Total: {{ calc.formatted.total }}
{{ /each }}
{{ /each }}
{{ #if(salesforce) }}
Customer: {{ salesforce.account_name }}
{{ /if }}
Dynamic hash fields
Several variables use dynamic keys (marked as “Hash” in the reference). These include custom_fields, custom_columns, summary, uom_fields, and product_custom_fields.
Access dynamic fields with dot notation using the field key:
«=option.custom_fields.my_custom_field»
«=calc.custom_columns.my_column»
«=salesforce.custom_fields.my_sf_field»
«=line.product_custom_fields.my_product_field»
The available keys depend on what custom fields you’ve configured in the Object Explorer , Display Options , and CRM field mapping .
Tips
Use formatted values for display. Most numeric fields have both a raw value (e.g., line.unit_price = 100.0) and a formatted version (e.g., line.formatted.unit_price = "$100.00"). Use the formatted versions in templates to get proper currency formatting without manual work.
Always wrap Salesforce data in conditionals. The salesforce object is null when no CRM is connected. Referencing salesforce.account_name without a conditional will produce an error in the generated document.
Use one_time_lines and recurring_lines for split tables. Instead of looping through all lines and checking the one_time flag on each, use the pre-filtered arrays for cleaner templates.
Test with a real quote. Generate a document from an actual quote to verify all merge fields resolve correctly. Nullable fields, empty arrays, and missing custom fields are the most common causes of template errors.
What’s next
Account Setup Configure the logo and brand color that appear in generated documents.
Quote Overview Understand the quote structure that document generation renders from.
Display Options Control what pricing detail appears in generated documents.
Web Portal Share interactive proposals alongside generated documents.