Skip to content

Order Notes

Overview

Order notes let customers attach free-text instructions to an order. There are two distinct kinds of note in the backend: per-item notes (one note per line item) and a single order-level note (one overall instruction for the whole order). Each kind has its own per-channel toggle — allow_notes for per-item notes and allow_order_notes for the order-level note — so a merchant can enable one without the other.

Key Purpose: Capture customer special requests and instructions, both per item and for the order as a whole, each independently switchable.

Purpose

When notes are enabled for a channel, customers can add a note to individual items and/or a single overall note to the order. The merchant enables each kind independently and configures its input placeholder text in the back office, per channel (In-House for kiosk, Online Settings for online ordering).

Key Concepts

  • Per-Item Notes: Stored on the TransactionItem model as a notes string (TransactionItem::getNotes()). Accepted on the create-intent request as items.*.notes (validated nullable|string).
  • Order-Level Note: A single optional note for the whole order, stored on the Transaction model as note (Transaction::getNote()). Accepted on the create-intent request as order_note (validated nullable|string|max:255). This is distinct from the per-item notes and is entered once at checkout.
  • Per-Channel Toggles (two, independent): allow_notes ({enabled, placeholder}) gates per-item notes; allow_order_notes ({enabled, placeholder}) gates the order-level note. Both are stored independently per channel: in the in-house setting for kiosk, and in the online settings for online ordering. A merchant can turn on one without the other — e.g. allow the order-level note but not per-item notes.
  • Backward Compatibility: allow_order_notes was split out of allow_notes after both existed as one combined toggle. If a tenant's saved settings have no allow_order_notes key yet, the API (ShowInHouseSettingsResource, ShowOnlineSettingsResource) mirrors allow_notes for it, and the save request (StoreInHouseSettingsRequest/StoreOnlineSettingsRequest) falls back to the submitted allow_notes value when allow_order_notes is absent from the payload — so pre-split behavior (one toggle controlling both) is preserved until the merchant explicitly configures allow_order_notes.
  • Sanitization (order note): The order note is sanitized server-side by TransactionService::sanitizeOrderNote() — HTML tags are stripped, whitespace is trimmed, the value is capped at 255 characters (Constants::ORDER_NOTE_MAX_LENGTH), and empty/whitespace-only input is stored as null.
  • POS Propagation: Both note kinds are forwarded to POS integrations that consume them — order note and item notes flow to Lightspeed K-Series, Kassanet, MplusKassa, ShopCaisse, and Square (order note); item notes also flow to Kassanet line items.

Actions

Enable Notes for a Channel

CheckoutNotes.vue renders two independent toggles, one per note kind, in In-House Settings (kiosk) or Online Settings (online ordering):

  • "Allow Item Notes" switch — sets allow_notes.enabled (per-item notes).
  • "Allow Order Notes" switch — sets allow_order_notes.enabled (order-level note).

Each toggle reveals its own placeholder textarea only when that toggle is on; the two can be switched on/off independently.

Set Placeholder Text

Each note kind has its own placeholder field, both required when their respective toggle is on and capped at 150 characters in the back office (requiredValidator + maxLengthValidator(..., 150) on the CheckoutNotes.vue textarea):

  • The per-item notes placeholder sets allow_notes.placeholder.
  • The order-level note placeholder sets allow_order_notes.placeholder.

Add a Note (Customer)

On the storefront, customers add a note per item and/or an order note at checkout.

Location

  • Backoffice Route: /in-house/settings (In-House — kiosk channel)
  • Backoffice Route: /online-settings (Online — online ordering channel)

The settings control is the shared CheckoutNotes.vue component, rendered in InHouseSettingsForm.vue (default mode) and OnlineSettingsForm.vue (mode="online-settings").

Fields

Notes Enabled (per-item)

PropertyValue
Field IDallow_notes.enabled
LabelAllow Item Notes
TypeToggle
Defaultfalse
Validation`required

Description: Enables per-item note input for customers on this channel.


Placeholder Text (per-item)

PropertyValue
Field IDallow_notes.placeholder
Label(back-office instruction: "Enter the placeholder text for the per-item 'add note' field. This guides customers in personalizing individual items.")
TypeText (textarea)
DefaultE.g. "For Oliver" or "I'm allergic to mushrooms (backend Constants default; the back-office textarea shows the hint text E.g. "For Oliver" or "I'm allergic to mushrooms")
Validationrequired when allow_notes.enabled is true, otherwise nullable; type string. Max 150 chars enforced in the back office only

Description: Hint text shown in the customer's per-item note input field. The back office requires this when per-item notes are enabled and caps it at 150 characters; the backend itself enforces only string (no length cap on the placeholder).


Order Notes Enabled (order-level)

PropertyValue
Field IDallow_order_notes.enabled
LabelAllow Order Notes
TypeToggle
Defaultfalse
Validation`required

Description: Enables the single whole-order note input for customers on this channel, independently of per-item notes. If a tenant has no saved allow_order_notes yet, the back office and API fall back to the value of allow_notes (see Backward Compatibility above).


Placeholder Text (order-level)

PropertyValue
Field IDallow_order_notes.placeholder
Label(back-office instruction: "Enter the placeholder text for the order-level note field. This guides customers in adding one instruction for the whole order.")
TypeText (textarea)
DefaultAdd a note for your whole order (backend Constants default; the back-office textarea shows the hint text E.g. "Please ring the doorbell" or "Leave at the front desk")
Validationrequired when allow_order_notes.enabled is true, otherwise nullable; type string. Max 150 chars enforced in the back office only

Description: Hint text shown in the customer's order-level note input field. The back office requires this when order notes are enabled and caps it at 150 characters; the backend itself enforces only string (no length cap on the placeholder).


Note Types

Item Notes

A free-text note attached to a single line item, stored on TransactionItem::notes.

Example use cases:

  • "No onions"
  • "Extra sauce"
  • "Well done"
  • "Allergies: nuts"

Order Note

A single free-text note for the whole order, stored on Transaction::note. Capped at 255 characters.

Example use cases:

  • "Please ring the doorbell"
  • "Leave at door"
  • "For Oliver's birthday"

Per-Channel Settings

In-House (Kiosk)

Stored in the in-house setting:

json
{
  "allow_notes": {
    "enabled": true,
    "placeholder": "Add special instructions..."
  },
  "allow_order_notes": {
    "enabled": true,
    "placeholder": "Add a note for your whole order"
  }
}

Online Ordering

Stored in the online settings:

json
{
  "allow_notes": {
    "enabled": true,
    "placeholder": "E.g. \"For Oliver\" or \"I'm allergic to mushrooms\""
  },
  "allow_order_notes": {
    "enabled": false,
    "placeholder": "Add a note for your whole order"
  }
}

Because the two toggles are independent, a channel can have allow_notes.enabled: true and allow_order_notes.enabled: false (or vice versa), as shown above.


Business Logic

Note Flow (configuration → capture)

Merchant enables "Allow Item Notes" and/or "Allow Order Notes" + sets placeholder(s) (per channel)

    ├── allow_notes.enabled = true ?
    │   ├── No  → no per-item note input shown to customer
    │   └── Yes → customer may add a note per item
    │                 │
    │                 ▼
    │             Create-intent request: items.*.notes → TransactionItem.notes

    └── allow_order_notes.enabled = true ?
        ├── No  → no order-level note input shown to customer
        └── Yes → customer may add one note for the whole order


                  Create-intent request: order_note → sanitizeOrderNote() → Transaction.note

Note: the two toggles are checked independently — a channel can show only the per-item note input, only the order-level note input, both, or neither. The order_note / items.*.notes request fields themselves are validated nullable by the backend regardless of the toggle state; the toggles gate whether the storefront/kiosk offers the input, not whether the backend accepts it if sent.

Note Propagation (to POS)

Transaction persisted

    ├── Order note  (Transaction::getNote())
    │     → Lightspeed K-Series, Kassanet, MplusKassa, ShopCaisse, Square

    └── Item notes  (TransactionItem::getNotes())
          → Lightspeed K-Series, Kassanet line items, MplusKassa

Business Rules

  • Per-item notes are gated by allow_notes.enabled; the order-level note is gated independently by allow_order_notes.enabled. When a flag is false, the customer is not offered that kind of note input.
  • If a tenant's saved settings predate the split (no allow_order_notes key stored), the API mirrors allow_notes for allow_order_notes in responses, and a save request that omits allow_order_notes falls back to the submitted allow_notes value — so old single-toggle behavior is preserved until the merchant explicitly sets allow_order_notes.
  • In the back office, both placeholder fields are required when their respective toggle ("Allow Item Notes" / "Allow Order Notes") is on (requiredValidator) and limited to 150 characters (maxLengthValidator(..., 150)). The backend validates each placeholder only as string (with required/nullable keyed off its own enabled flag) and applies no length cap.
  • The order note is server-sanitized: HTML stripped, trimmed, capped at 255 characters (Constants::ORDER_NOTE_MAX_LENGTH), and empty/whitespace-only values are stored as null.
  • Per-item notes (items.*.notes) are validated nullable|string — there is no backend length cap on item notes.
  • Per-item notes persist on TransactionItem; the order note persists on Transaction. Both are exposed to the customer via OrderDetailResource (item note, order-level note) and forwarded to the POS integrations listed above.

FAQs

  • "Is there an order-level note, or only per-item notes?" Both. Per-item notes live on TransactionItem::notes; there is also a single order-level note on Transaction::note (request field order_note), capped at 255 characters.
  • "Can I enable item notes without order notes, or vice versa?" Yes. allow_notes (per-item) and allow_order_notes (order-level) are separate settings, each with its own {enabled, placeholder}, and each toggle in the back office ("Allow Item Notes" / "Allow Order Notes") can be switched independently.
  • "Where are note settings configured?" In two places, each independent: In-House Settings (/in-house/settings, kiosk) and Online Settings (/online-settings, online ordering). Each place has two separate toggles, one for item notes and one for order notes. QR ordering has no allow_notes/allow_order_notes setting in the backend.
  • "Why does my order-level note setting show the same value as my item notes setting?" If allow_order_notes hasn't been saved for that channel yet (e.g. it predates the split into two toggles), the back office and API fall back to the allow_notes value for it. Save the settings page once with the desired "Allow Order Notes" value to set it explicitly.
  • "What is the maximum length for notes?" The order note is capped server-side at 255 characters (Constants::ORDER_NOTE_MAX_LENGTH). Per-item notes have no backend length cap (nullable|string). The 150-character limit applies to the merchant-configured placeholder text for both toggles in the back office, not to customer notes.
  • "What is the default placeholder?" For per-item notes, the backend Constants default is E.g. "For Oliver" or "I'm allergic to mushrooms, and the back-office hint text is E.g. "For Oliver" or "I'm allergic to mushrooms". For the order-level note, the backend Constants default is Add a note for your whole order, and the back-office hint text is E.g. "Please ring the doorbell" or "Leave at the front desk". Both note kinds are off by default (enabled: false).
  • "Do notes reach the POS / kitchen?" Yes. The order note is sent to Lightspeed K-Series, Kassanet, MplusKassa, ShopCaisse, and Square; item notes are sent to Lightspeed K-Series, Kassanet line items, and MplusKassa.

Customer Impact

  • When per-item notes are enabled (allow_notes.enabled), customers can add a note per item at checkout; when order-level notes are enabled (allow_order_notes.enabled), customers can add a single overall order note. The two are independent, so a channel may offer only one, both, or neither.
  • Notes are returned in the customer's order detail (OrderDetailResource): each item carries a singular note, and the order carries an order-level note.

Troubleshooting

  • No per-item note input shown to the customer → Verify "Allow Item Notes" (allow_notes.enabled) is on for the correct channel: In-House Settings for kiosk, Online Settings for online ordering.
  • No order-level note input shown to the customer → Verify "Allow Order Notes" (allow_order_notes.enabled) is on for the correct channel. This is a separate toggle from "Allow Item Notes" — enabling one does not enable the other.
  • Order note appears truncated → The order note is capped at 255 characters server-side; longer input is trimmed by sanitizeOrderNote().
  • Note not reaching a POS → Confirm the POS integration is one that consumes notes (Lightspeed K-Series, Kassanet, MplusKassa, ShopCaisse, or Square for the order note). Other channels may not forward notes.

Assistant Guidance

When answering questions about this feature:

  • Treat "Allow Notes" / "notes setting" as ambiguous — always clarify whether the merchant means the per-item toggle (allow_notes, back-office label "Allow Item Notes") or the order-level toggle (allow_order_notes, back-office label "Allow Order Notes"). They are two separate settings, not one.
  • If a merchant reports their order-level note setting mysteriously matches their item-note setting, explain the backward-compat fallback: allow_order_notes falls back to allow_notes until it's explicitly saved for that channel.
  • Always specify which channel: In-House Settings (/in-house/settings, kiosk) and Online Settings (/online-settings, online ordering) hold separate copies of both toggles. QR ordering has neither setting.
  • The 150-character limit is on the merchant-configured placeholder text in the back office, not on what customers type; the customer-facing order note is capped at 255 characters server-side, and per-item notes have no backend length cap.

Relations

Affects

  • Transactions: Order note stored on Transaction; item notes on TransactionItem
  • POS integrations: Notes forwarded to Lightspeed K-Series, Kassanet, MplusKassa, ShopCaisse, Square

Examples

Notes Enabled (channel setting, both toggles)

json
{
  "allow_notes": {
    "enabled": true,
    "placeholder": "Special instructions..."
  },
  "allow_order_notes": {
    "enabled": true,
    "placeholder": "Add a note for your whole order"
  }
}

Create-Intent Request (item note + order note)

json
{
  "items": [
    { "id": "item-123", "notes": "No basil, extra cheese" }
  ],
  "order_note": "Please include extra napkins"
}

Persisted Transaction (resolved fields)

json
{
  "items": [
    { "name": "Margherita Pizza", "notes": "No basil, extra cheese" }
  ],
  "note": "Please include extra napkins"
}