Documentation Index

Fetch the complete documentation index at: https://help.quickbase.com/llms.txt

Use this file to discover all available pages before exploring further.

Jinja reference

Prev Next

Note: This page is a reference. Use the table of contents or Ctrl+F to find what you need.

Quick syntax cheat sheet

Shape

What it does

Example

{{ value }}

Show a value

{{a.first_name}}

{% statement %}

Do something (if, for, set…)

{% if a.amount > 100 %}

{# comment #}

A note that doesn't appear in the output

{# remember to update this #}

|

Apply a filter to a value

{{a.name | upper}}

~

Stitch two strings together

{{a.first ~ '-' ~ a.last}}

.

Reach a field on an object

{{a.first_name}}

['…']

Reach a field whose name has spaces

{{a['Date Created']}}

[0]

Reach the first item in a list

{{b[0].name}}

About Jinja in Pipelines

Pipelines runs Jinja version 2.11.3 in a limited environment. You can't import Python modules, read files from disk, or call out to the network from inside a Jinja expression. Everything you can do is on this page.

Jinja isn't the Quickbase formula language. The two share goals (turn data into something useful) but have different syntax. Many filters below have a close equivalent in formulas, called out in the Quickbase formula column. Treat the mapping as a loose match, not exact.

Variables—dot, bracket, get, set

3 ways to reach a field on a step:

Way to write it

When to use

{{a.field_name}}

Standard: name is one word, no spaces or special characters

{{a['Field Name']}}

The field name has spaces, or matches a reserved word

{{a.get('field_name', 'fallback')}}

The field might not exist; supply a default

Create your own variable:

{% set total = 0 %}
{% set greeting = 'Hello, ' ~ a.first_name %}

For a variable you want to update inside a loop, use namespace(). Learn more in Pipelines-specific extras.

Statements, expressions, comments

{{ value }}       # show a value
{% statement %}   # do something — if, for, set
{# comment #}     # leave a note that won't appear in the output

Comments are useful for temporarily disabling a block of Jinja while you debug.

If / elif / else

{% if a.amount > 1000 %}Big
{% elif a.amount > 100 %}Medium
{% else %}Small
{% endif %}
  • {% if … %}—the first question

  • {% elif … %}—(optional, can have many) another question if the previous was no

  • {% else %}—(optional) what to do if nothing matched

  • {% endif %}—closes the block

To learn more, refer to Start with Jinja in Pipelines.

For loops and loop helpers

{% for r in b %}
{{r.name}}
{% endfor %}

Inside any loop, these helpers are available:

Helper

What it gives you

loop.index

Position of the current item, starting at 1

loop.index0

Position of the current item, starting at 0

loop.first

true on the first item only

loop.last

true on the last item only

loop.length

Total number of items

loop.revindex

Position counted from the end, starting at 1

loop.previtem

The previous item (not available on the first)

loop.nextitem

The next item (not available on the last)

To learn more, refer to Start with Jinja in Pipelines.

Whitespace control

Jinja keeps the whitespace around your statements by default, which can break JSON payloads or leave empty lines. Add a hyphen to either side to strip whitespace:

{%- if a.amount > 100 -%}
  • {%- strips whitespace before the tag

  • -%} strips whitespace after the tag

The same works for expressions: {{- value -}}.

Filters by category

A filter changes a value, applied with the pipe character |. Filters chain: {{a.notes | striptags | trim | upper}} strips HTML, trims whitespace, then uppercases, in that order.

Date/time

Filter

What it does

Example

Quickbase formula

time.now

Current date and time, in UTC

{{time.now}}

Now()

time.today

Today's date at 00:00 UTC

{{time.today}}

Today()

time.delta(…)

Add or subtract a span of time. Plural arg (days=7) adds; singular arg (day=15) sets that part absolutely

{{time.today + time.delta(days=7)}}

+ ToDuration()

time.parse(string)

Turn a date-shaped string into a real date

{{time.parse('2025-01-15').strftime('%B %d')}}

ToDate()

timezone(code)

Convert UTC to a specific timezone. Codes from the tz database

{{time.now | timezone('America/New_York')}}

date_ymd(separator?)

Format as year-month-day. Default separator is -

{{time.now | date_ymd}}2025-01-15

ToFormattedText()

date_mdy(separator?)

Format as month-day-year

{{time.now | date_mdy('/')}}01/15/2025

ToFormattedText()

date_dmy(separator?)

Format as day-month-year

{{time.now | date_dmy('.')}}15.01.2025

ToFormattedText()

.strftime(format)

Custom date format. Method, not filter. Use dot notation, not pipe

{{time.now.strftime('%a, %B %d')}}

ToFormattedText()

.date()

Drop the time portion off a date/time

{{a.created_at.date()}}

ToDate()

.days

When you subtract two dates, get the number of days as a number

{{(a.end - a.start).days}}

ToDays()

.seconds

When you subtract two dates, get the number of seconds

{{(a.end - a.start).seconds}}

timestamp_to_time(value)

Convert a Unix timestamp (seconds since 1970) to UTC

{{1608112432 | timestamp_to_time}}12-16-2020 01:53 AM

Note: .strftime and .find are methods, not filters. Use value.strftime(...), not value | strftime(...). The pipe form silently does the wrong thing.

Common strftime format codes:

Code

Result

%Y

Year, 4 digits (2025)

%m

Month, 2 digits (01–12)

%d

Day, 2 digits (01–31)

%B

Month name (January)

%b

Month abbreviated (Jan)

%A

Weekday name (Monday)

%a

Weekday abbreviated (Mon)

%H

Hour, 24-hour (00–23)

%I

Hour, 12-hour (01–12)

%M

Minute (00–59)

%S

Second (00–59)

%p

AM or PM

Text

Filter

What it does

Example

Quickbase formula

upper

Make all uppercase

{{a.name | upper}}

ToUpper()

lower

Make all lowercase

{{a.name | lower}}

ToLower()

title

Capitalize the first letter of each word

{{a.name | title}}

capitalize

Capitalize the first letter, lowercase the rest

{{a.name | capitalize}}

trim

Remove whitespace from the ends

{{a.name | trim}}

Trim()

replace(old, new)

Replace a substring

{{a.value | replace('$', '')}}

SearchAndReplace()

length

Number of characters

{{a.name | length}}

Length()

wordcount

Number of words

{{a.notes | wordcount}}

slice(start, end)

Take a portion of a string. Use value[start:end] syntax

{{a.code[2:6]}}

Mid()

~

Stitch two strings together

{{a.first ~ ' ' ~ a.last}}

&

.split(delimiter)

Split a string into a list by a delimiter (method)

{{a.email.split('@')[1]}} — gets the domain

Part()

.find(substring)

Position of a substring (-1 if not found). Method, not filter

{{a.text.find('hello')}}

striptags

Remove all HTML/XML tags

{{a.html_field | striptags}}

text

Strip HTML and formatting from a rich text field

{{a.notes | text}}

html2text

Convert HTML to Markdown

{{a.body | html2text}}

escape

Convert <, >, &, quotes to HTML-safe entities

{{a.name | escape}}

urlencode

Make a string safe to use in a URL

{{a.search | urlencode}}

format(args)

Insert values into a template string

{{ "Hello, %s" | format(a.name) }}

tojson / to_json

Convert to JSON-safe text. Use when building JSON payloads, as it handles escaping automatically

"name": {{a.name | tojson}}

safe

Mark a value as already safe; skip escaping

{{a.html | safe}}

truncate(length)

Shorten a string and add ...

{{a.notes | truncate(50)}}

Numbers

Filter

What it does

Example

Quickbase formula

int

Convert to a whole number

{{a.text | int}}

ToNumber()

float

Convert to a decimal number

{{a.text | float}}

ToNumber()

round(precision)

Round to a number of decimals

{{a.amount | round(2)}}

Round()

abs

Absolute value (drop the minus sign)

{{a.delta | abs}}

Abs()

max

Largest value in a list

{{[1,2,3] | max}}

Max()

min

Smallest value in a list

{{[1,2,3] | min}}

Min()

Lists and aggregation

These work on lists—usually a search step's output, or a multi-select or List-User field.

Filter

What it does

Example

length / count

Number of items

{{b | length}}

first

First item

{{b | first}}

last

Last item

{{b | last}}

sort

Sort the list. Add attribute='field' for lists of records

{{b | sort(attribute='name')}}

unique

Remove duplicates

{{b | unique}}

join(separator)

Stitch list items into one string

{{['a','b','c'] | join(',')}}a,b,c

sum

Sum a list of numbers. Add attribute='field' for records. Fails on null values; use namespace() for null safety

{{b | sum(attribute='amount')}}

map(attribute='x')

Pull one field out of each record

{{b | map(attribute='email') | list}}

select(test)

Keep only items that pass a test

{{[1,2,3,4] | select('odd') | list}}

reject(test)

Drop items that pass a test

{{[1,2,3,4] | reject('odd') | list}}

selectattr(attr, test, value)

Keep records whose field passes a test

{{b | selectattr('status', 'equalto', 'Open') | list}}

rejectattr(attr, test, value)

Drop records whose field passes a test

{{b | rejectattr('status', 'equalto', 'Closed') | list}}

list

Force the result into a list. Often needed after map, select, and similar filters

{{b | map(attribute='id') | list}}

range(start, end)

Generate a list of numbers from start to end-1

{{range(1, 6) | list}}[1,2,3,4,5]

random

Pick a random item

{{['a','b','c'] | random}}

Encoding and hashing

Filter

What it does

base64_encode / base64_decode

Encode or decode a string in Base64. Used for embedding files in JSON payloads

md5

MD5 hash

sha1 / sha224 / sha256 / sha384 / sha512

SHA hash family

hmac(key, algorithm)

Hash-based message authentication code, used for signing API requests

Other

Filter

What it does

Example

Quickbase formula

default(value)

Use a fallback if input is undefined or empty

{{a.note | default('No notes')}}

Nz()

string

Force a value into a string

{{a.value | string}}

ToText()

Tests

A test asks a yes/no question about a value. Tests use the word is, not the pipe character.

{% if a.field is defined %}...{% endif %}
{% if a.field is none %}...{% endif %}
{% if a.amount is number %}...{% endif %}

Test

True when…

defined

The variable exists

none

The value is empty / null

string

The value is text

number

The value is a number

integer

The value is a whole number

float

The value is a decimal number

boolean

The value is true or false

iterable

The value can be looped through (a list, for example)

mapping

The value is a key-value object (like a JSON object)

sequence

The value is an ordered collection (a list or a string)

odd

The number is odd

even

The number is even

divisibleby(n)

The number divides evenly by n

equalto / eq

Equals a given value

ne

Not equal to

lt / le / gt / ge

Less / less-or-equal / greater / greater-or-equal

in

The value is in a given list or string

Combine with not to invert: {% if a.field is not none %}.

Pipelines-specific extras

These features are added by Pipelines on top of standard Jinja.

The runtime object

Every pipeline run has a runtime object with metadata about itself.

Property

What it gives you

runtime.pipeline_name

User-defined pipeline name

runtime.pipeline_id

Numeric pipeline ID

runtime.pipeline_url

Link to the pipeline editor

runtime.run_id

Unique ID of this run

runtime.activity_url

Direct link to this run in the activity log

runtime.triggered_at

UTC timestamp of when the run started

runtime.user_id

Pipelines user ID of whoever triggered the run

Example—build a clickable link into an error alert:

Pipeline "{{runtime.pipeline_name}}" failed.
View activity: {{runtime.activity_url}}

The trigger context object (Quickbase triggers)

On a Quickbase trigger step, a.context gives you details about the app and table that fired the run.

Property

What it gives you

a.context.app_name

The app name

a.context.app_id

The app ID

a.context.table_name

The table name

a.context.table_id

The table ID

a.context.realm_host

Your Quickbase realm host

a.context.realm_id

Numeric realm ID

a.context.occurred_at

When the change happened, UTC

a.context.user

The user who triggered the change

$prev

Access the previous value of a field when the trigger was a Record Updated event. Goes between the step letter and the field name:

{% if a.status != a.$prev.status %}...{% endif %}

Only available on update triggers. Does not work in Quickbase Advanced Query filter strings. See Start with Jinja in Pipelines for the full explanation.

{{CLEAR}}

Explicitly empty a field in a write step. By default, Pipelines silently skips empty values to prevent accidental data loss. Use {{CLEAR}} to override that.

{% if a.priority == 'No priority' %}{{CLEAR}}{% else %}{{a.priority}}{% endif %}

raise_error(message)

Stop a pipeline run with a custom error message. Useful for input validation.

{% if a.amount > 10000 %}{{raise_error('Amount over the limit')}}{% endif %}

joiner() and namespace()

Two helpers for situations where standard Jinja has limitations.

joiner(separator) builds a comma-separated list inside a loop without a leading or trailing separator. The first call returns nothing; every subsequent call returns the separator.

{% set comma = joiner(', ') %}
{% for c in b %}{{comma()}}{{c.name}}{% endfor %}

Produces Alice, Bob, Carol with no leading or trailing comma.

namespace(...) is a container for variables that need to change inside a loop. A normal {% set %} inside a loop only updates for that iteration; namespace persists the value across iterations.

Most common use: a running total that ignores nulls.

{% set total = namespace(value=0) %}
{% for r in b %}
  {% set total.value = total.value + (r.amount | default(0, true)) %}
{% endfor %}
Total: {{total.value}}

Advanced Query—Quickbase query syntax

Warning: Advanced Query / filter fields on Quickbase search and trigger steps use Quickbase query syntax, not Jinja. When you select code mode on one of these fields, you're typing query syntax. Jinja can still be embedded inside the value portion—see Embed Jinja inside a query below.

Query format

Each query is wrapped in curly braces and has three parts separated by periods:

{fid.OPERATOR.'matching_value'}
  • fid—the field's numeric ID

  • OPERATOR—uppercase, from the table below

  • matching_value—what to compare against, in single quotes

Example—find records where field 6 equals "Open":

{6.EX.'Open'}

Combine multiple conditions with AND or OR (always uppercase), grouped with parentheses:

({6.EX.'Open'}OR{6.EX.'In Progress'})AND{13.OAF.'01-01-2025'}

Common operators

Operator

What it does

Example

EX

Equals exactly

{6.EX.'Open'}

XEX

Not equal

{6.XEX.'Closed'}

CT

Contains substring (text)

{12.CT.'urgent'}

SW

Starts with (text)

{12.SW.'INV-'}

BF / AF / OAF

Before / after / on or after (date)

{13.OAF.'01-01-2025'}

LT / LTE / GT / GTE

Less / less-or-equal / greater / greater-or-equal (numbers)

{19.GT.'1000'}

HAS

Contains a value (multi-select, List-User)

{20.HAS.'alice@example.com'}

IR

In a relative date range ('today', 'yesterday', and similar)

{13.IR.'today'}

For the full operator list, see Components of a Query.

Compare one field to another

Use _FID_n as the matching value to compare two fields on the same record:

{6.EX._FID_8}

Returns records where field 6 equals field 8.

Embed Jinja inside a query

The matching value portion can contain Jinja, evaluated at runtime. The outer query syntax stays the same; the inner {{…}} produces the value.

Find records modified in the last 5 minutes:

{2.OAF.'{{time.now + time.delta(minutes=-5)}}'}

Find records owned by the user who triggered the run:

{8.EX.'{{a.context.user}}'}

Find records matching a value from step a:

{6.EX.'{{a.customer_id}}'}

Two things that don't work inside a query:

  • $prev—only works in regular Jinja value expressions, not in query strings

  • Multi-line Jinja with {% … %} statements—keep it to a single {{ … }} expression

What isn't supported

Things you might expect to work but don't:

  • {% break %} and {% continue %} inside loops. Use select / reject filters to filter the list before looping, or wrap the loop body in an {% if %}.

  • {% include %}, {% import %}, {% extends %}—Pipelines doesn't allow template inheritance.

  • Importing Python modules.

  • Reading or writing files outside the pipeline.

  • The do extension ({% do … %}).

Reserved words

A few attribute names conflict with built-in Jinja or Python concepts and can't be reached with dot notation. Use bracket notation instead.

Field name

Use this instead of b.field_name

items

b['items']

keys

b['keys']

values

b['values']

update

b['update']