<!-- GENERATED FILE. Do not edit by hand.
     Source: src/lib/variables/catalog.ts
     Regenerate: bun x tsx scripts/generate-variables-doc.ts
     Guarded by: tests/docs/variables-doc.test.ts -->

# Variables

Every value a store can put into a notification, a document or a page, as a
named token. Write `{{ order.total }}` and the store fills in the amount, in
its own currency, formatted the way the rest of the platform formats money.
There are 117 of them across 14 scopes, and this page is generated
from the same catalog the renderer resolves from, so it cannot drift.

## Syntax

Dotted paths, the shape Shopify and Klaviyo both use, so what you already
know transfers:

```liquid
Hi {{ customer.first_name }}, order {{ order.number }} is on its way.
Total {{ order.total }} including {{ order.tax }} VAT.
Track it: {{ delivery.tracking_number }}
```

Whitespace inside the braces is optional. A variable the store cannot answer
renders as nothing, never as the raw `{{ ... }}`: a customer must never see
template syntax.

## Two rules worth knowing

**The platform formats, you place.** Money carries the order's currency,
dates carry the platform's date format, statuses carry the same words the
admin shows ("Unpaid", "Partially shipped"). You never format a value
yourself, and the same amount looks identical in an email, on an invoice and
in an API response.

**Product names, not column names.** The token is `{{ order.number }}`, and
it resolves to the store's own order number when the store has one. Database
column names never appear here.

## Scopes

A scope is a group of related variables. Which ones a given notification
carries depends on what that notification is about: an order confirmation
carries the order, the customer, both addresses, the delivery and the store,
while a purchase order carries the purchase order, the supplier and the
store.

### Order

Every customer notification carries it. Money is formatted in the order's own currency.

| Variable | What it is | Format | Also accepts |
|---|---|---|---|
| `{{ order.number }}` | The number the customer sees. The store's own number when it has one, otherwise the platform sequence. | text | `{{display_id}}`, `{{order_number}}` |
| `{{ order.id }}` | Internal identifier. Useful in links and API calls, not in customer copy. | text |  |
| `{{ order.url }}` | Link to the customer's own order page. Built per store and per order: the store's custom domain when it has one, otherwise its Cartbase address. | url | `{{order_url}}` |
| `{{ order.email }}` | The address the order was placed with. | email |  |
| `{{ order.date }}` | When the order was placed. | date |  |
| `{{ order.status }}` | Lifecycle state: pending, completed, canceled or archived. | text |  |
| `{{ order.payment_status }}` | Paid, Awaiting payment, Refunded and so on, in the same words the admin uses. | text |  |
| `{{ order.fulfillment_status }}` | Unfulfilled, Shipped, Delivered and so on, in the same words the admin uses. | text |  |
| `{{ order.locale }}` | Language the customer shopped in, when the storefront sends one. | text |  |
| `{{ order.cancelled_at }}` | When the order was cancelled, if it was. | datetime |  |
| `{{ order.item_count }}` | Total number of units in the order. | number |  |
| `{{ order.currency }}` | Currency code the order was placed in. | text |  |
| `{{ order.total }}` | What the customer pays, everything included. | money | `{{order_total}}`, `{{total}}` |
| `{{ order.subtotal }}` | Items only, before tax, shipping and discounts. | money |  |
| `{{ order.tax }}` | Total tax on the order. | money |  |
| `{{ order.shipping }}` | What delivery cost the customer. | money |  |
| `{{ order.discount }}` | Total discount applied to the order. | money |  |
| `{{ order.cod_fee }}` | Courier fee charged for paying on delivery. | money |  |
| `{{ order.paid }}` | How much has actually been captured so far. | money |  |
| `{{ order.refunded }}` | How much has been refunded. | money |  |
| `{{ order.balance_due }}` | What is still outstanding on the order. | money |  |

### Customer

The email address is the customer's identity here, so every order carries a customer. Names fall back to the shipping then the billing address.

| Variable | What it is | Format | Also accepts |
|---|---|---|---|
| `{{ customer.name }}` | Full name of the customer. | text | `{{customer_name}}` |
| `{{ customer.first_name }}` | First name on its own, for a greeting. | text |  |
| `{{ customer.last_name }}` | Last name on its own. | text |  |
| `{{ customer.email }}` | The customer's email address, which is their identity here. | email |  |
| `{{ customer.phone }}` | Phone number on the customer record. | text |  |
| `{{ customer.company }}` | Company name for business customers. | text |  |
| `{{ customer.vat_number }}` | VAT number for business customers, needed on invoices. | text |  |
| `{{ customer.eik }}` | Bulgarian EIK for business customers. | text |  |
| `{{ customer.tags }}` | Tags on the customer, comma separated. | text |  |

### Shipping address

Every field individually, plus a one-line `formatted` version.

| Variable | What it is | Format | Also accepts |
|---|---|---|---|
| `{{ shipping_address.formatted }}` | The whole address on one line, ready to drop into a sentence. | text |  |
| `{{ shipping_address.name }}` | Recipient's full name. | text |  |
| `{{ shipping_address.first_name }}` | Recipient's first name. | text |  |
| `{{ shipping_address.last_name }}` | Recipient's last name. | text |  |
| `{{ shipping_address.company }}` | Company on the address, when given. | text |  |
| `{{ shipping_address.line_1 }}` | Street and number. | text |  |
| `{{ shipping_address.line_2 }}` | Apartment, floor, or extra detail. | text |  |
| `{{ shipping_address.city }}` | City or town. | text |  |
| `{{ shipping_address.province }}` | Province, region or state. | text |  |
| `{{ shipping_address.postal_code }}` | Postal code. | text |  |
| `{{ shipping_address.country }}` | Two-letter country code. | text |  |
| `{{ shipping_address.phone }}` | Phone number on the address. | text |  |

### Billing address

The same field set as the shipping address.

| Variable | What it is | Format | Also accepts |
|---|---|---|---|
| `{{ billing_address.formatted }}` | The whole address on one line, ready to drop into a sentence. | text |  |
| `{{ billing_address.name }}` | Recipient's full name. | text |  |
| `{{ billing_address.first_name }}` | Recipient's first name. | text |  |
| `{{ billing_address.last_name }}` | Recipient's last name. | text |  |
| `{{ billing_address.company }}` | Company on the address, when given. | text |  |
| `{{ billing_address.line_1 }}` | Street and number. | text |  |
| `{{ billing_address.line_2 }}` | Apartment, floor, or extra detail. | text |  |
| `{{ billing_address.city }}` | City or town. | text |  |
| `{{ billing_address.province }}` | Province, region or state. | text |  |
| `{{ billing_address.postal_code }}` | Postal code. | text |  |
| `{{ billing_address.country }}` | Two-letter country code. | text |  |
| `{{ billing_address.phone }}` | Phone number on the address. | text |  |

### Delivery

Reads the order's most recent live fulfillment and its first label.

| Variable | What it is | Format | Also accepts |
|---|---|---|---|
| `{{ delivery.method }}` | The shipping option the customer chose, in the merchant's own words. | text |  |
| `{{ delivery.price }}` | What the chosen delivery method cost. | money |  |
| `{{ delivery.carrier }}` | The courier carrying the parcel. | text |  |
| `{{ delivery.tracking_number }}` | Waybill number the customer can track. | text | `{{tracking_number}}` |
| `{{ delivery.tracking_url }}` | Direct link to the courier's tracking page for this parcel. | url |  |
| `{{ delivery.pickup_location }}` | Courier office or locker the customer chose. | text |  |
| `{{ delivery.shipped_at }}` | When the parcel left the store. | datetime |  |
| `{{ delivery.delivered_at }}` | When the courier delivered the parcel. | datetime |  |

### Store

The store's public identity. `store.email` is the address a reply reaches.

| Variable | What it is | Format | Also accepts |
|---|---|---|---|
| `{{ store.name }}` | The store's name. | text | `{{store_name}}` |
| `{{ store.url }}` | Link to the storefront: the custom domain when there is one. | url |  |
| `{{ store.email }}` | Where customers reach the store. The sender address when set, otherwise the owner's account email. | email | `{{support_email}}` |
| `{{ store.address }}` | Registered address of the business. | text |  |
| `{{ store.vat_number }}` | The business VAT number. | text |  |
| `{{ store.eik }}` | Bulgarian EIK of the business. | text |  |
| `{{ store.iban }}` | Bank account customers pay into. | text |  |

### Cart

For abandoned-cart flows. Supplied by the caller, not by an order.

| Variable | What it is | Format | Also accepts |
|---|---|---|---|
| `{{ cart.id }}` | Identifier of the customer's cart. | text |  |
| `{{ cart.total }}` | What is in the cart, priced. | money |  |
| `{{ cart.item_count }}` | How many units are in the cart. | number |  |

### Document

Read from the document's frozen snapshot, never from the live order, because orders change and documents must not.

| Variable | What it is | Format | Also accepts |
|---|---|---|---|
| `{{ document.number }}` | Number of the invoice or other document. | text | `{{document_number}}` |
| `{{ document.type }}` | Invoice, proforma, dispatch note or handover protocol. | text | `{{document_type}}` |
| `{{ document.date }}` | Date the document was issued. | date |  |
| `{{ document.url }}` | Link to download the PDF. | url |  |
| `{{ document.currency }}` | Currency the document is issued in. | text |  |
| `{{ document.payment_method }}` | How the document says payment is made. | text |  |
| `{{ document.due_date }}` | When the invoice is due. | date |  |
| `{{ document.outstanding }}` | How much of the invoice is still unpaid. | money |  |
| `{{ document.paid_at }}` | When the invoice was settled. | datetime |  |
| `{{ document.voided_at }}` | When the document was voided, if it was. | datetime |  |
| `{{ document.issuer.name }}` | Legal name of the issuer. | text |  |
| `{{ document.issuer.address }}` | Registered address of the issuer. | text |  |
| `{{ document.issuer.eik }}` | Bulgarian EIK / company registration number. | text |  |
| `{{ document.issuer.vat_number }}` | VAT registration number. | text |  |
| `{{ document.issuer.mol }}` | Materially responsible person (Bulgarian invoicing). | text |  |
| `{{ document.issuer.iban }}` | Bank account for payment. | text |  |
| `{{ document.recipient.name }}` | Legal name of the recipient. | text |  |
| `{{ document.recipient.address }}` | Registered address of the recipient. | text |  |
| `{{ document.recipient.eik }}` | Bulgarian EIK / company registration number. | text |  |
| `{{ document.recipient.vat_number }}` | VAT registration number. | text |  |
| `{{ document.recipient.mol }}` | Materially responsible person (Bulgarian invoicing). | text |  |
| `{{ document.recipient.iban }}` | Bank account for payment. | text |  |
| `{{ document.totals.subtotal }}` | Line items on the document, before tax. | money |  |
| `{{ document.totals.discount }}` | Discount on the document. | money |  |
| `{{ document.totals.shipping }}` | Shipping on the document. | money |  |
| `{{ document.totals.tax }}` | Tax on the document. | money |  |
| `{{ document.totals.tax_rate_percent }}` | Effective VAT percentage shown on the document. | percent |  |
| `{{ document.totals.total }}` | The amount the document is for. | money |  |

### Purchase order

| Variable | What it is | Format | Also accepts |
|---|---|---|---|
| `{{ purchase_order.number }}` | Number of the purchase order sent to a supplier. | text | `{{po_number}}` |
| `{{ purchase_order.status }}` | Where the purchase order stands. | text |  |
| `{{ purchase_order.total }}` | Value of the purchase order. | money |  |
| `{{ purchase_order.expected_at }}` | When the goods are expected. | date |  |

### Supplier

| Variable | What it is | Format | Also accepts |
|---|---|---|---|
| `{{ supplier.name }}` | Name of the supplier the purchase order goes to. | text | `{{supplier_name}}` |
| `{{ supplier.email }}` | Where the purchase order is sent. | email |  |
| `{{ supplier.phone }}` | Supplier phone number. | text |  |

### Review

| Variable | What it is | Format | Also accepts |
|---|---|---|---|
| `{{ review.url }}` | Link to the review form for this order. | url |  |
| `{{ review.product_title }}` | The product being reviewed. | text | `{{product_title}}` |
| `{{ review.reward_percentage }}` | Discount percentage earned for leaving a review. | number | `{{reward_percentage}}` |
| `{{ review.reward_code }}` | The single-use discount code earned for a review. | text | `{{reward_code}}` |

### Gift card

The amount only. The card CODE is never a variable: it renders as a fixed block so an edited template cannot drop it or leak it.

| Variable | What it is | Format | Also accepts |
|---|---|---|---|
| `{{ gift_card.amount }}` | Value loaded on the gift card. | money | `{{gift_card_amount}}` |
| `{{ gift_card.expires_at }}` | When the gift card stops working, if it expires. | date |  |

### Subscription

| Variable | What it is | Format | Also accepts |
|---|---|---|---|
| `{{ subscription.plan_name }}` | The subscription plan the customer is on. | text | `{{plan_name}}` |
| `{{ subscription.next_charge_date }}` | When the subscription renews next. | text | `{{next_charge_date}}` |

### Alert

Staff operational alerts only.

| Variable | What it is | Format | Also accepts |
|---|---|---|---|
| `{{ alert.title }}` | Headline of the operational alert. | text | `{{alert_title}}` |
| `{{ alert.detail }}` | What the system check found. | text |  |

## What each notification carries

| Notification | Scopes |
|---|---|
| Order Confirmation | Order, Customer, Shipping address, Billing address, Delivery, Store |
| Order Shipped | Order, Customer, Shipping address, Billing address, Delivery, Store |
| Order Delivered | Order, Customer, Shipping address, Billing address, Delivery, Store |
| Order Refunded | Order, Customer, Shipping address, Billing address, Delivery, Store |
| Order Cancelled | Order, Customer, Shipping address, Billing address, Delivery, Store |
| Admin: New Order | Order, Customer, Shipping address, Billing address, Delivery, Store |
| Welcome Email | Customer, Store |
| Password Reset | Customer, Store |
| Document Issued | Order, Customer, Shipping address, Billing address, Delivery, Store, Document |
| Sign-in Code | Customer, Store |
| B2B Account Approved | Customer, Store |
| Review Request | Order, Customer, Shipping address, Billing address, Delivery, Store, Review |
| Review Reward Code | Order, Customer, Shipping address, Billing address, Delivery, Store, Review |
| Out for Delivery | Order, Customer, Shipping address, Billing address, Delivery, Store |
| Ready for Pickup | Order, Customer, Shipping address, Billing address, Delivery, Store |
| Picked Up | Order, Customer, Shipping address, Billing address, Delivery, Store |
| Econt Office Reminder (Day 3) | Order, Customer, Shipping address, Billing address, Delivery, Store |
| Econt Office Reminder (Day 5) | Order, Customer, Shipping address, Billing address, Delivery, Store |
| Admin: System Alert | Alert, Store |
| Gift Card Delivery | Order, Customer, Shipping address, Billing address, Delivery, Store, Gift card |
| Purchase Order | Purchase order, Supplier, Store |
| Subscription: Upcoming Renewal | Order, Customer, Shipping address, Billing address, Delivery, Store, Subscription |
| Subscription: Payment Failed | Order, Customer, Shipping address, Billing address, Delivery, Store, Subscription |
| Subscription: Paused | Order, Customer, Shipping address, Billing address, Delivery, Store, Subscription |
| Subscription: Canceled | Order, Customer, Shipping address, Billing address, Delivery, Store, Subscription |

Writing a variable from a scope the notification does not carry is refused
when you save it, with the reason, rather than rendering as a blank in a real
customer's inbox.

## Not available yet

These are real product gaps, listed so they are visible rather than promised.
They are not offered in the editor and cannot be saved into a template.

| Variable | What it would be | What is missing |
|---|---|---|
| `{{ order.note }}` | The note the customer left with their order. | not collected yet |
| `{{ store.phone }}` | The number customers can call. | no column yet |
| `{{ cart.url }}` | Link that puts the customer back in their abandoned cart. | storefront cart recovery route plus the cart id |

## Never variables

The **gift card code** and the **sign-in code** render as fixed blocks and
are deliberately not tokens. An edited template must not be able to drop them
(the customer loses their code) or move them somewhere they leak.
