Endpoint templates are written with {{ token }} placeholders that RackHelm fills in from the order being processed. This article lists every token available, explains how values are substituted, and covers the Data exposure tab — the allowlist that decides which of a customer’s own order variables an integration may send to a third party.
How substitution works #
Three rules govern every template, and they are what makes an operator-authored JSON body safe to send:
- Values are substituted, not text. RackHelm walks the decoded template and replaces values as PHP values, encoding the whole document to JSON once at the end. A customer whose company name contains a quote or a brace cannot break the structure of your payload.
- Keys are literal. A token in a key position is never rendered, so a template can never introduce a field you did not type. The endpoint form surfaces such a token so you find out at save time.
- A substituted value is never re-scanned. A customer whose address line literally reads
{{ client.email }}gets that text sent verbatim.
Types are preserved when a value stands alone. "{{ var.Seats }}" as an entire string emits the number 4, so an API that validates types accepts it; the same token embedded in a longer string is stringified. Booleans become 1 and 0 rather than an empty string, arrays become compact JSON, and dates become ISO-8601.
Tokens in the Path are URL-encoded, so a value containing / or .. cannot re-point the request at another resource. Tokens in the Query template that resolve to nothing are dropped rather than sent empty.
No token ever survives onto the wire. Anything that cannot be resolved becomes null (if it was the whole value) or an empty string (if it was embedded), and is listed on the delivery row as an unresolved token.
The token reference #
The endpoint modal offers all of these as clickable buttons: allowlisted variables first, then values this integration has captured, then a Context tokens disclosure with the fixed list.
Fixed namespaces #
| Namespace | Keys |
|---|---|
event |
name, id, occurred_at, attempt, idempotency_key |
integration |
slug, name |
item |
id, type, status, provisioning_status, quantity, unit_price, setup_fee, expires_at, created_at, external_id, cancellation_reason |
order |
id, order_number, status, due_date, billing_cycle, billing_cycle_months |
product |
id, name, group |
client |
id, email, first_name, last_name, name, company, phone |
address |
line1, line2, city, state, postcode, country |
invoice |
id, number, total, status, paid_at |
Note: There is no
order.totaltoken. An order carries no total of its own in RackHelm — money for an order lives on its invoice, so use{{ invoice.total }}.
Free-form namespaces #
| Token | What it resolves to |
|---|---|
{{ var.KEY }} |
An order variable the customer chose at checkout — a custom-field value or an addon value. Only keys on this integration’s allowlist resolve. |
{{ attr.KEY }} |
A value this integration captured from an earlier reply, decrypted for use. See Endpoints. |
{{ config.KEY }} |
A key from the product’s own integration configuration. This is not the application configuration — no application secret is reachable through it. |
Standalone tokens #
| Token | What it resolves to |
|---|---|
{{ vars }} |
The whole allowed variable bag as an object. Useful when the remote API takes a free-form settings blob. |
{{ uuid }} |
A random identifier, stable for the life of one call — a re-render for a retry produces the same value rather than minting a new one. |
{{ now }} |
ISO-8601 timestamp. Also accepts a format: now.iso, now.date, now.time, now.datetime, now.timestamp, now.unix. Every now in one payload agrees. |
Tip: Variable keys are case-sensitive and are stored exactly as they appear on the order, punctuation and spaces included —
{{ var.Elementor Advanced }}is a legitimate token. Only the namespace half is case-insensitive.
The Data exposure tab #

Variables this integration may send #
The multi-select lists every custom field key on the system. Hold Ctrl (or Cmd) to select several. Keys already on the allowlist that no longer exist as custom fields are still offered and stay selected, so re-saving the form cannot silently drop a token a live endpoint depends on.
The list is fail-closed: an empty allowlist allows nothing at all, not everything. That is why a brand-new integration cannot send order variables until you name them here, and why an endpoint template that references an un-allowed variable is rejected when you save it rather than quietly rendering a hole on the wire.
Both spellings are accepted in the stored list — the bare key and the qualified var.KEY form — because the editor shows tokens qualified while the values themselves are stored under the bare key.
Note: Variable keys beginning
environment.are reserved for the game and control-panel drivers and can never be templated, whatever the allowlist says. If the list is empty because no custom fields exist yet, create them under Catalogue → Custom Fields first.
Credentials in payloads #
Allow password-like variables to be sent is off by default and should stay off unless the remote API genuinely needs a credential. With it off, any variable backed by a custom field of type password is stripped from the bag before rendering, even if it is on the allowlist. With it on, those values are interpolated into the request body, travel to a third party, and are then written to the delivery log where any member of staff who can read integration logs can see them.
Checking what a template will actually send #
Use Test → Preview (sends nothing). It renders the payload through exactly the same code path a live provision uses — allowlist filtering and redactions included — and shows you the method, URL, headers, body, query and, most usefully, the list of tokens that did not resolve. Nothing leaves the box.

Troubleshooting #
| Symptom | Cause and fix |
|---|---|
Unknown token namespace "customer" |
The customer namespace is called client. The message lists every known namespace. |
"item" needs a key. Valid keys: … |
A bare namespace token is refused — it would serialise a whole record. Name the field you want. |
Variables beginning "environment." are reserved… |
Panel startup variables cannot be templated. Use a custom field instead. |
| A token saved fine but the delivery lists it as unresolved | The token is valid but the record behind it is absent for this service — no invoice on the order, no address, no product. A field that exists and is simply empty resolves to null and is not reported. |
| A password value arrives empty at the provider | Allow password-like variables to be sent is off. Turn it on only if the provider genuinely requires it. |
| An addon value is missing from the payload | Addon values are written under the addon’s own name. Check the exact key on the order, then add that key to the allowlist. |
| The provider rejects a numeric field sent as a string | Put the token on its own — "seats": "{{ var.Seats }}" emits a number; "seats": "x{{ var.Seats }}" emits a string. |