# Print Templates Reference

This is the technical reference for the <code class="expression">space.vars.productName</code> print template system. Templates are HTML with special variable placeholders that are replaced with real transaction data at print time.

For the visual template editors, see [Receipt Templates](/netsuite-admin-guide/overview-2/receipt-templates.md), [Invoice Templates](/netsuite-admin-guide/overview-2/invoice-templates.md), and [Label Templates](/netsuite-admin-guide/overview-2/label-templates.md).

## How variables resolve

Two main namespaces feed every template:

* **`payload.*`:** the order submission payload that's about to be sent to NetSuite. Use this for transaction-scoped data (line items, payment data, custom body fields).
* **`store.*`:** the current <code class="expression">space.vars.productName</code> app state at print time. Use this for location, user, totals, and other "ambient" values.

Variables written without a prefix (e.g. `{{date}}`, `{{subtotal}}`) are auto-resolved: the system looks first in the payload, then in the store.

The **Recommended Variables** panel inside each template editor (Receipt / Invoice / Label) shows you the exact paths available; click a variable chip to insert it into the HTML.

## Payload — `payload.*`

Variables that come from the order submission payload (the record being created in NetSuite).

| Variable                                                  | Description                                                       |
| --------------------------------------------------------- | ----------------------------------------------------------------- |
| `{{payload.fields.entity}}`                               | Customer ID                                                       |
| `{{payload.fields.subsidiary}}`                           | Subsidiary ID                                                     |
| `{{payload.fields.externalid}}`                           | Order / receipt number                                            |
| `{{payload.fields.location}}`                             | Location ID                                                       |
| `{{payload.fields.trandate.date}}`                        | Transaction date                                                  |
| `{{payload.fields.custbody_brm_order_type}}`              | Order type code                                                   |
| `{{payload.fields.custbody_brm_order_id}}`                | BRM order ID                                                      |
| `{{payload.fields.custbody_brm_createdby}}`               | User ID who created the order                                     |
| `{{payload.fields.custbody_brm_cash_drawer}}`             | Cash drawer ID                                                    |
| `{{payload.sublists.item\|items}}`                        | Line items array: formatted as a table by the `\|items` formatter |
| `{{payload.metadata.paymentData.payments\|payments}}`     | Payments array: formatted as a list by the `\|payments` formatter |
| `{{payload.metadata.paymentData.totals.remainingAmount}}` | Remaining amount on the order                                     |

Other `custbody_*` fields configured on your transaction form are also available via `{{payload.fields.custbody_<field_id>}}`.

## Store — `store.*`

Variables that come from the <code class="expression">space.vars.productName</code> app store at print time.

| Variable                                      | Description                                                                   |
| --------------------------------------------- | ----------------------------------------------------------------------------- |
| `{{store.locationSettings.name}}`             | Current location name                                                         |
| `{{store.locationSettings.id}}`               | Current location ID                                                           |
| `{{store.locationSettings.phone}}`            | Location phone                                                                |
| `{{store.locationSettings.address\|address}}` | Location address (formatted with line breaks by the `\|address` formatter)    |
| `{{store.currentUser.name}}`                  | Logged-in user's name                                                         |
| `{{store.currentUser.email}}`                 | Logged-in user's email                                                        |
| `{{store.currentUser.id}}`                    | Logged-in user's ID                                                           |
| `{{store.totals.subtotal}}`                   | Subtotal                                                                      |
| `{{store.totals.tax}}`                        | Tax                                                                           |
| `{{store.totals.total}}`                      | Grand total                                                                   |
| `{{store.totals.discount}}`                   | Order-level discount                                                          |
| `{{store.totals.shipping}}`                   | Shipping total                                                                |
| `{{store.lineItems\|items}}`                  | Line items array: same shape as `payload.sublists.item`, formatted as a table |
| `{{store.brmOrderId}}`                        | BRM order ID                                                                  |
| `{{store.recordFields}}`                      | All form fields on the current record, with their labels                      |

## Auto-resolved (no prefix)

These resolve from the payload first, then the store. Use them when you want short, readable templates.

| Variable           | Description                                          |
| ------------------ | ---------------------------------------------------- |
| `{{subtotal}}`     | Subtotal: auto-formatted as currency                 |
| `{{tax}}`          | Tax: auto-formatted as currency                      |
| `{{total}}`        | Total: auto-formatted as currency                    |
| `{{items\|items}}` | Line items array: used with the `\|items` formatter  |
| `{{payments}}`     | Payments array: used with the `\|payments` formatter |
| `{{date}}`         | Transaction date                                     |

{% hint style="info" %}
Auto-currency formatting kicks in automatically for fields whose names contain `total`, `subtotal`, `tax`, `price`, or `amount`. You don't need `|currency` on those; but adding it is harmless.
{% endhint %}

## Format specifiers

Append a pipe and a specifier name to apply formatting.

| Specifier    | Example                                               | Effect                                       |
| ------------ | ----------------------------------------------------- | -------------------------------------------- |
| `\|currency` | `{{store.totals.total\|currency}}`                    | `$1,250.00`                                  |
| `\|items`    | `{{store.lineItems\|items}}`                          | Renders the items array as an HTML table     |
| `\|payments` | `{{payload.metadata.paymentData.payments\|payments}}` | Renders the payments array as an HTML list   |
| `\|address`  | `{{store.locationSettings.address\|address}}`         | Renders an address object as multi-line HTML |

## Loops and conditionals

Templates support Handlebars-style block helpers for iterating and conditional rendering.

### Looping over line items

Use `{{#each store.lineItems}}` (or `{{#each payload.sublists.item}}`) to iterate. Inside the block, refer to the current item as `item`:

```html
{{#each store.lineItems}}
  <div style="display: flex; justify-content: space-between;">
    <span>{{item.quantity}} × {{item.name}}</span>
    <span>{{item.price|currency}}</span>
  </div>
{{/each}}
```

### Conditionals

Use `{{#if ...}}` to render content only when a condition is true:

```html
{{#if item.customFields.special}}
  ⭐ Special item
{{/if}}

{{#if item.quantity >= 10}}
  <div style="font-size: 10px;">Bulk discount applied</div>
{{/if}}
```

## Example: a basic receipt template

```html
<div style="font-family: monospace; width: 300px;">
  <h2 style="margin: 0;">{{store.locationSettings.name}}</h2>
  <div style="font-size: 12px;">{{store.locationSettings.address|address}}</div>
  <hr/>
  <p>Receipt #: {{payload.fields.externalid}}</p>
  <p>Date: {{date}}</p>
  <hr/>
  {{#each store.lineItems}}
    <div style="display: flex; justify-content: space-between;">
      <span>{{item.quantity}} × {{item.name}}</span>
      <span>{{item.price|currency}}</span>
    </div>
  {{/each}}
  <hr/>
  <div>Subtotal: {{store.totals.subtotal|currency}}</div>
  <div>Tax: {{store.totals.tax|currency}}</div>
  <div><strong>Total: {{store.totals.total|currency}}</strong></div>
  <hr/>
  <div>Payments: {{payload.metadata.paymentData.payments|payments}}</div>
  <hr/>
  <p>Served by: {{store.currentUser.name}}</p>
</div>
```

## Tips

* **Use the Recommended Variables panel** in the editor: clicking a variable chip inserts the exact path. Manually typed paths are easy to typo.
* **Keep templates narrow:** most thermal receipt printers output at 58 mm or 80 mm. Aim for an outer container `width` of 280–380 px.
* **Test in the Preview panel** before assigning a template to a live printer.
* **If a variable outputs blank**, check that the field exists on the transaction type you're printing. Not every field is present on every transaction; `payload.fields.custbody_*` fields depend on your custom form configuration.

## Related Pages

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Receipt Templates</strong></td><td>The visual editor for POS receipts.</td><td><a href="/pages/8hHHrjkvabDRVl6pLjNM">/pages/8hHHrjkvabDRVl6pLjNM</a></td></tr><tr><td><strong>Invoice Templates</strong></td><td>The visual editor for invoice documents.</td><td><a href="/pages/ratQ79sBuy8vJWucXwwq">/pages/ratQ79sBuy8vJWucXwwq</a></td></tr><tr><td><strong>Label Templates</strong></td><td>The visual editor for item / shelf labels.</td><td><a href="/pages/CJVG1785aVbqh1gdDo06">/pages/CJVG1785aVbqh1gdDo06</a></td></tr><tr><td><strong>Module Variables</strong></td><td>How to populate Store Variables from within a workflow.</td><td><a href="/pages/S9QlmvCWJ8AOsDrFpQtz">/pages/S9QlmvCWJ8AOsDrFpQtz</a></td></tr></tbody></table>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.in8sync.com/netsuite-admin-guide/overview-2/printers-and-templates.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
