Skip to main content

Complete Filters Reference Guide

What This Guide Is

This is your complete reference for filtering records in Apper's API. We'll explain:

  • How Apper's filtering system works (concepts first)
  • Every available operator and when to use it
  • How to build complex queries step-by-step

Who is this for? Developers integrating with Apper who need to search/filter records programmatically.

Prerequisites: You should be familiar with the Apper API Documentation basics (authentication, making requests, etc.).


Filtering 101: Core Concepts

Before diving into specific operators, let's understand how Apper's filtering system works.

The Basic Filter Structure

Every filter condition has four parts:

{
"fieldName": "Status", // Which field to check
"operator": "Contains", // How to compare
"values": ["Active"], // What to compare against
"include": true // Include or exclude matches
}
Breaking it down:

  • fieldName: The column/field you're filtering on (must match exactly)
  • operator: The comparison type (contains, greater than, etc.)
  • values: An array of values to compare (even for single values, use an array)

Include = Whether to include (true) or exclude (false) matching records

Understanding AND vs OR Logic

Apper gives you two ways to combine filters:

Simple AND Logic: The "where" Array

What this means: "Give me records where Status = Active AND State = California"

All conditions in the where array must be true.

{
"where": [
{ "fieldName": "Status", "operator": "Includes", "values": ["Active"] },
{ "fieldName": "State", "operator": "Includes", "values": ["California"] }
]
}
Complex AND/OR Logic: The "whereGroups" Array

What this means: "Give me records where State = California OR State = Texas"

Use whereGroups when you need OR logic between different fields.

{
"whereGroups": [
{
"operator": "OR",
"subGroups": [
{
"operator": "OR",
"conditions": [
{ "fieldName": "State", "operator": "Includes", "values": ["California"] },
{ "fieldName": "State", "operator": "Includes", "values": ["Texas"] }
]
}
]
}
]
}

Example scenarios:

What You WantUse This
Active customers in Californiawhere (both conditions must be true)
Customers in California or TexaswhereGroups (either state can match)
Active customers in California or TexasBothwhere for Active, whereGroups for states
The "include" Parameter: Inverting Logic

Every filter has an optional include parameter:

  • "include": true (default) = Include matching records
  • "include": false = Exclude matching records (adds a NOT)
When to use include: false:
  • Excluding specific values (easier than listing all other values)
  • Date ranges you want to avoid ("not in the last 30 days")
  • Status exclusions ("everything except Draft and Deleted")

Quick Decision Guide: Which Operator?

Choose the right operator based on what you're trying to do:

"I want records where the value..."

You Want…OperatorExample
Text Searches
Contains this textContainsName contains "Tech"
Doesn’t contain this textNotContainsEmail doesn’t contain "spam"
Starts with this textStartsWithPhone starts with "+1"
Ends with this textEndsWithWebsite ends with ".com"
Is one of several valuesIncludesStatus in ["Active", "Pending"]
Is none of several valuesExcludesType not in ["Draft", "Archived"]
Numerical Comparisons
Is greater thanGreaterThanAmount > 1000
Is less thanLessThanStock < 10
Is at least (≥)GreaterThanOrEqualToScore ≥ 75
Is at most (≤)LessThanOrEqualToAge ≤ 65
Is between two numbersExactMatch + BetweenPrice between 50 and 100
Date Comparisons
Is in this time periodRelativeMatchCreatedOn in "this month"
Is a specific dateEqualTo or ExactMatchDate = "2025-01-15"
Is before / after a dateLessThan / GreaterThanDueDate < "2025-12-31"

"I need to combine multiple conditions..."

You WantUse ThisExample Logic
All conditions must be truewhere arrayA AND B AND C
Any condition can be trueIncludes or whereGroupsA OR B OR C
Complex nested logicwhereGroups(A AND B) OR (C AND D)

Text Field Filters

Applies to: Text, Email, Phone, Website, MultilineText, Picklist, Radio, AutoNumber

Text fields are probably the most common thing you'll filter. Here are all the operators and when to use each.

Exact Matching

NotEqualTo

When to use: You want everything except one specific value.

{
"fieldName": "Status",
"operator": "NotEqualTo",
"values": ["Deleted"]
}
Includes (Multiple Exact Values)

When to use: You want records matching any of several exact values (OR logic).

{
"fieldName": "Priority",
"operator": "Includes",
"values": ["High", "Critical", "Urgent"]
}

What this means: "Give me records where Priority is High OR Critical OR Urgent"

Excludes (Exclude Multiple Values)

When to use: You want to exclude several specific values.

{
"fieldName": "Type",
"operator": "Excludes",
"values": ["Draft", "Archived", "Deleted"]
}

What this means: "Give me all records except those with Type = Draft, Archived, or Deleted"

Partial Text Matching

Contains

When to use: You're searching for text anywhere in the field (like a search box).

{
"fieldName": "CompanyName",
"operator": "Contains",
"values": ["Tech"]
}
Matches:

  • "TechCorp"
  • "FinTech Solutions"
  • "Advanced Technologies"
  • "tech startup" (case-insensitive)
Doesn't match:

  • "ABC Company"
  • "Global Industries"
NotContains

When to use: You want to exclude records with certain text.

{
"fieldName": "Email",
"operator": "NotContains",
"values": ["test"]
}

Matches: All emails that don't have "test" anywhere in them

StartsWith

Field value starts with the specified text.

{
"fieldName": "Phone",
"operator": "StartsWith",
"values": ["+1"]
}

Matches: "+1-555-1234", "+1 (555) 5678"

NotStartsWith

Field value does not start with the specified text.

{
"fieldName": "OrderNumber",
"operator": "NotStartsWith",
"values": ["TEST"]
}
EndsWith

Field value ends with the specified text.

{ 
"fieldName": "Email",
"operator": "EndsWith",
"values": [".edu"]
}

Matches: "example.com", "website.com"

NotEndsWith

Field value does not end with the specified text.

{
"fieldName": "Website",
"operator": "NotEndsWith",
"values": [".gov"]
}

Alphabetical Comparison

These operators compare text alphabetically (A→Z ordering).

GreaterThan

When to use: Alphabetical sorting/filtering.

{
"fieldName": "Name",
"operator": "GreaterThan",
"values": ["M"]
}

Matches: "Nancy", "Oliver", "Zoe" (names starting with letters after M)

ExactMatch with Multiple Values

Match exact values from a list.

{
"fieldName": "Status",
"operator": "ExactMatch",
"include": true,
"values": ["Active", "Pending"]
}
Exclude specific values:

{
"fieldName": "Type",
"operator": "ExactMatch",
"include": false,
"values": ["Draft", "Archived"]
}

Number Field Filters

Applies to: Number, Decimal, Currency

Basic Operators

NotEqualTo

Not equal to the specified number.

{
"fieldName": "Amount",
"operator": "NotEqualTo",
"values": [0]
}
GreaterThan

Greater than the specified number.

{
"fieldName": "Price",
"operator": "GreaterThan",
"values": [99.99]
}
LessThan

Less than the specified number.

{
"fieldName": "Stock",
"operator": "LessThan",
"values": [10]
}
GreaterThanOrEqualTo

Greater than or equal to the specified number.

{
"fieldName": "Score",
"operator": "GreaterThanOrEqualTo",
"values": [75]
}
LessThanOrEqualTo

Less than or equal to the specified number.

{
"fieldName": "Age",
"operator": "LessThanOrEqualTo",
"values": [65]
}

Range Filtering with ExactMatch + Between

For numeric ranges, use the Between subOperator with ExactMatch.

Between Two Values
{
"fieldName": "Age",
"operator": "ExactMatch",
"subOperator": "Between",
"values": [25 and 40]
}

What this means: Age ≥ 25 AND Age ≤ 40 (inclusive on both ends)

Exclude a Range
{
"fieldName": "Score",
"operator": "ExactMatch",
"subOperator": "Between",
"include": false,
"values": [0 and 50]
}

What this means: Exclude scores between 0 and 50 (only show 51+)

Below a Value (Less Than or Equal)
{
"fieldName": "Price",
"operator": "ExactMatch",
"subOperator": "Between",
"values": ["below 100"]
}

Format: "below {value}"

What this means: Price ≤ 100

Above a Value (Greater Than or Equal)
{
"fieldName": "Revenue",
"operator": "ExactMatch",
"subOperator": "Between",
"values": ["5000 and above"]
}

Format: "{value} and above"

What this means: Revenue ≥ 5000

Multiple Specific Values
{
"fieldName": "Quantity",
"operator": "Includes",
"values": ["10", "25", "50", "100"]
}

What this means: Quantity is 10 OR 25 OR 50 OR 100

Text Operators on Numbers (Advanced)

You can use text operators like Contains on number fields:

{
"fieldName": "Phone",
"operator": "Contains",
"values": [555]
}

Matches: Any phone number containing "555" (e.g., 555-1234, 123-555-7890)

Use case: Searching for partial numbers, area codes, or patterns.


Date & DateTime Field Filters

Applies to: Date, DateTime

Basic Operators

GreaterThan

After the specified date.

{
"fieldName": "StartDate",
"operator": "GreaterThan",
"values": ["2025-01-01"]
}
LessThan

Before the specified date.

{
"fieldName": "ExpiryDate",
"operator": "LessThan",
"values": ["2025-12-31"]
}

Relative Date Filters

Relative date filters use natural language for dynamic date ranges.

This/Last/Next Period
This Week/Month/Quarter/Year:
{
"fieldName": "CreatedOn",
"operator": "RelativeMatch",
"values": ["this month"]
}

Available values: "this year", "this quarter", "this month", "this week"

Last Period:
{
"fieldName": "PurchaseDate",
"operator": "RelativeMatch",
"values": ["last quarter"]
}

Available values: "last year", "last quarter", "last month", "last week", "last day", "last hour"

Next Period:
{
"fieldName": "RenewalDate",
"operator": "RelativeMatch",
"values": ["next month"]
}

Available values: "next year", "next quarter", "next month", "next week", "next day", "next hour"

Exact Date Values
Today/Yesterday/Tomorrow
{
"fieldName": "AppointmentDate",
"operator": "RelativeMatch",
"values": ["Today"]
}

Available values: "Today", "Yesterday", "Tomorrow"

Last N Periods

Records from the last N time units.

{
"fieldName": "LastLogin",
"operator": "RelativeMatch",
"values": ["last 30 day"]
}

Format: "last {number} {period}" where period can be: year, quarter, month, week, day, hour

Examples:

  • "last 30 day" - Last 30 days
  • "last 3 month" - Last 3 months
  • "last 2 year" - Last 2 years
Next N Periods

Records in the next N time units.

{
"fieldName": "SubscriptionExpiry",
"operator": "RelativeMatch",
"values": ["next 14 day"]
}

Format: "next {number} {period}"

Examples:

  • "next 7 day" - Next 7 days
  • "next 2 week" - Next 2 weeks
  • "next 6 month" - Next 6 months
Before/After N Periods

Records exactly N periods before or after today

{
"fieldName": "InvoiceDate",
"operator": "RelativeMatch",
"values": ["before 30 day"]
}

Format: "before {number} {period}" or "after {number} {period}"

This N Period

Records within a specific recent timeframe.

{
"fieldName": "ModifiedOn",
"operator": "RelativeMatch",
"values": ["this 2 week"]
}

Format: "{period}" where period can be: this week, this month, this year.

Same date, different year

Use case: Annual recurring dates (birthdays, anniversaries)

{
"fieldName": "Birthday",
"operator": "RelativeMatch",
"values": ["same date different year"]
}

If today is January 15, find all January 15 records across all years.

Today of Year:

Use case: Same as "same date different year"

{
"fieldName": "Anniversary",
"operator": "RelativeMatch",
"values": ["Today of year"]
}

Note: Works the same as "same date different year"

Today of Month:

Use case: Same as "same day of month""

{
"fieldName": "MonthlyReport",
"operator": "RelativeMatch",
"values": ["Today of month"]
}

Exclude Date Ranges

Use "include": false to exclude date ranges.

{
"fieldName": "CreatedOn",
"operator": "RelativeMatch",
"include": false,
"values": ["last 30 day"]
}

Excludes records from the last 30 days

Filtering by Date Components with ExactMatch

Sometimes you want to filter by a specific part of a date (year, month, etc.) without caring about the full date.

Year
{
"fieldName": "CreatedOn",
"operator": "ExactMatch",
"subOperator": "Year",
"values": ["2024"]
}
Quarter
{
"fieldName": "SalesDate",
"operator": "ExactMatch",
"subOperator": "Quarter",
"values": ["1 2025"]
}

Format: "{quarter} {year}" where quarter is 1, 2, 3, or 4

Month
{
"fieldName": "TransactionDate",
"operator": "ExactMatch",
"subOperator": "Month",
"values": ["Jan 2025"]
}

Format: "{month} {year}" where month is Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec

Week
{
"fieldName": "WeeklyReport",
"operator": "ExactMatch",
"subOperator": "Week",
"values": ["W37 2025"]
}

Format: "{weekNumber} {year}"

Day
{
"fieldName": "EventDate",
"operator": "ExactMatch",
"subOperator": "Day",
"values": ["15 Jan 2025"]
}

Format: "{day} {month} {year}"

DateTime
{
"fieldName": "Timestamp",
"operator": "ExactMatch",
"subOperator": "DateTime",
"values": ["01-15-2025 14:30:00"]
}

Format: "{month}-{day}-{year} {time}"


Boolean Field Filters

Applies to: Boolean (Yes/No, True/False checkboxes)

Boolean filtering is straightforward but has a few syntax options.

ExactMatch

Filter by true/false values.

True:
{
"fieldName": "IsActive",
"operator": "ExactMatch",
"values": ["true"]
}
False:
{
"fieldName": "IsVerified",
"operator": "ExactMatch",
"values": ["false"]
}

Include Null (Empty) Values:

Use case:
  • When a checkbox hasn't been set yet (null)
  • Optional checkboxes with no default value
  • Including "not set" in your results
{
"fieldName": "IsApproved",
"operator": "ExactMatch",
"values": ["", "true"]
}

Matches both empty/null values AND true values

EqualTo (Alternative Syntax)

Boolean fields also support numeric notation:

True (1):
{
"fieldName": "IsActive",
"operator": "EqualTo",
"values": ["1"]
}
False (0):
{
"fieldName": "IsActive",
"operator": "EqualTo",
"values": ["0"]
}

Picklist & Multi-Select Filters

Applies to: Picklist, Radio, Multipicklist, Checkbox, Tag

Single Selection Fields (Picklist, Radio)

Use standard text operators:
{
"fieldName": "Priority",
"operator": "EqualTo",
"values": ["High"]
}
Multiple options (OR logic):
{
"fieldName": "Status",
"operator": "Includes",
"values": ["Open", "In Progress", "Pending"]
}

Multi-Select Fields (Multipicklist, Checkbox, Tag)

Contains (Any Match)

Records containing ANY of the specified values (OR logic).

{
"fieldName": "Tags",
"operator": "Contains",
"values": ["urgent", "important"]
}

Matches records with "urgent" OR "important" OR both

EqualTo (Exact Match - Single Value)

Records with exactly one specific value selected.

{
"fieldName": "Categories",
"operator": "EqualTo",
"values": ["Marketing"]
}
EqualTo (All Match - Multiple Values)

Records containing ALL specified values (AND logic).

{
"fieldName": "Skills",
"operator": "EqualTo",
"values": ["JavaScript", "React", "Node.js"]
}

Only matches records that have all three skills selected

ExactMatch

Precise match of selected options.

{
"fieldName": "Permissions",
"operator": "ExactMatch",
"values": ["Read", "Write"]
}
NotContains

Exclude records containing specific values.

{
"fieldName": "Tags",
"operator": "NotContains",
"values": ["archived"]
}

Lookup & Reference Field Filters

Applies to: Lookup, MasterDetail

Lookup fields reference records in other tables. Filter by the ID of the referenced record.

Basic Filtering

EqualTo

Records linked to a specific record.

{
"fieldName": "Company",
"operator": "EqualTo",
"values": [123]
}

Where 123 is the ID of the company record

Includes

Records linked to any of the specified records (OR logic).

{
"fieldName": "AssignedTo",
"operator": "Includes",
"values": [45, 67, 89]
}

Matches records assigned to user 45 OR 67 OR 89

ExactMatch

Match specific reference IDs

{
"fieldName": "RelatedProject",
"operator": "ExactMatch",
"values": [301, 302]
}

Exclude specific references:

{
"fieldName": "Owner",
"operator": "ExactMatch",
"include": false,
"values": [999]
}

Filtering by Reference Field Properties

You can filter by properties of the referenced record using subOperators.

Numeric Properties

Filter by numeric fields in the referenced table:

{
"fieldName": "RelatedAccount",
"operator": "ExactMatch",
"subOperator": "Between",
"values": ["1000 and above"]
}

Where RelatedAccount has a numeric field you're filtering on


Advanced: Complex Logic with WhereGroups

WhereGroups allow you to build complex queries with nested AND/OR logic.

Structure

{
"whereGroups": [
{
"operator": "AND",
"subGroups": [
{
"operator": "OR",
"conditions": [
{ /* filter 1 */ },
{ /* filter 2 */ }
]
}
]
}
]
}

Example 1: (A OR B) AND C

Find active customers in California OR Texas:

{
"where": [
{
"fieldName": "Status",
"operator": "EqualTo",
"values": ["Active"]
}
],
"whereGroups": [
{
"operator": "AND",
"subGroups": [
{
"operator": "OR",
"conditions": [
{
"fieldName": "State",
"operator": "EqualTo",
"values": ["California"]
},
{
"fieldName": "State",
"operator": "EqualTo",
"values": ["Texas"]
}
]
}
]
}
]
}

Logic: Status = Active AND (State = California OR State = Texas)

Example 2: (A AND B) OR (C AND D)

Find high-value customers OR recent signups:

{
"whereGroups": [
{
"operator": "OR",
"subGroups": [
{
"operator": "AND",
"conditions": [
{
"fieldName": "TotalSpent",
"operator": "GreaterThan",
"values": [10000]
},
{
"fieldName": "Type",
"operator": "EqualTo",
"values": ["Enterprise"]
}
]
},
{
"operator": "AND",
"conditions": [
{
"fieldName": "CreatedOn",
"operator": "RelativeMatch",
"values": ["last 30 day"]
},
{
"fieldName": "Status",
"operator": "EqualTo",
"values": ["Trial"]
}
]
}
]
}
]
}

Logic: (TotalSpent > 10000 AND Type = Enterprise) OR (CreatedOn in last 30 days AND Status = Trial)

Example 3: Complex Multi-Level Logic

Find qualified leads:

{
"whereGroups": [
{
"operator": "AND",
"subGroups": [
{
"operator": "OR",
"conditions": [
{
"fieldName": "Source",
"operator": "EqualTo",
"values": ["Website"]
},
{
"fieldName": "Source",
"operator": "EqualTo",
"values": ["Referral"]
}
]
},
{
"operator": "AND",
"conditions": [
{
"fieldName": "Score",
"operator": "GreaterThanOrEqualTo",
"values": [75]
},
{
"fieldName": "Budget",
"operator": "ExactMatch",
"subOperator": "Between",
"values": ["5000 and above"]
}
]
}
]
}
]
}

Logic: (Source = Website OR Source = Referral) AND (Score >= 75 AND Budget >= 5000)


Best Practices

1. Start Simple

Begin with basic where conditions before moving to complex whereGroups.

2. Use Appropriate Operators

  • Text searches: Use Contains for partial matches, EqualTo for exact matches
  • Dates: Prefer RelativeMatch for dynamic queries ("this month" vs hardcoded dates)
  • Numbers: Use range operators (Between, GreaterThan, LessThan) for better flexibility

3. Handle Null Values

Empty values are treated as null. To include/exclude nulls:

{
"fieldName": "Description",
"operator": "ExactMatch",
"values": ["", "value"]
}

4. Test Incrementally

Build complex filters step-by-step:

  • Test each condition individually
  • Combine with AND logic
  • Add OR logic if needed
  • Add nested groups last

5. Performance Tips

  • Limit the number of fields returned in the fields array
  • Use pagination for large result sets
  • Index frequently filtered fields in your Apper app

Common Use Cases

Find Overdue Tasks

{
"where": [
{
"fieldName": "Status",
"operator": "NotEqualTo",
"values": ["Completed"]
},
{
"fieldName": "DueDate",
"operator": "LessThan",
"values": ["2025-01-15"]
}
]
}

Find New High-Value Customers

{
"where": [
{
"fieldName": "CreatedOn",
"operator": "RelativeMatch",
"values": ["last 90 day"]
},
{
"fieldName": "TotalPurchases",
"operator": "GreaterThan",
"values": [5000]
}
]
}

Find Expiring Subscriptions

{
"where": [
{
"fieldName": "ExpiryDate",
"operator": "RelativeMatch",
"values": ["next 30 day"]
},
{
"fieldName": "Status",
"operator": "EqualTo",
"values": ["Active"]
}
]
}

Find Inactive Users

{
"where": [
{
"fieldName": "LastLoginDate",
"operator": "RelativeMatch",
"include": false,
"values": ["last 90 day"]
}
]
}

Troubleshooting

Common Issues

Issue: Filter returns no results
Solution: Check field name spelling (case-sensitive), verify field type matches operator.

Issue: Date filters not working
Solution: Ensure date format matches field type (Date vs DateTime), use ISO 8601 format.

Issue: Lookup filters not matching
Solution: Use record IDs, not display names. Get IDs from the related table first.

Issue: Multiple conditions are not combining correctly
Solution: Remember: where uses AND logic, use whereGroups for OR logic


Quick Reference Cheat Sheet

Text Operators

NeedOperatorExample
Contains textContainsCompany contains "Tech"
Starts withStartsWithPhone starts with "+1"
Ends withEndsWithEmail ends with ".com"
One of many valuesIncludesStatus in ["Active", "Pending"]
None of theseExcludesType not in ["Draft", "Test"]

Number Operators

NeedOperatorExample
Greater thanGreaterThanAmount > 1000
Less thanLessThanStock < 10
BetweenExactMatch + BetweenAge between 25 and 40
Below a valueExactMatch + BetweenPrice below 100
Above a valueExactMatch + BetweenSales 5000 and above

Date Operators

NeedOperator + ValueExample
Current periodRelativeMatch"this month"
Last periodRelativeMatch"last quarter"
Next periodRelativeMatch"next week"
Last N daysRelativeMatch"last 30 day"
Specific dateEqualTo"2025-01-15"
Before / after a dateLessThan / GreaterThanBefore "2025-12-31"
Specific yearExactMatch + YearYear = 2024
Specific monthExactMatch + MonthMonth = Jan 2025

Boolean

NeedOperator + ValueExample
TrueExactMatch["true"]
FalseExactMatch["false"]
True or nullExactMatch["", "true"]

Multi-Select

NeedOperatorLogic
Has any of theseContainsOR
Has all of theseEqualTo (multiple values)AND
Has exactly theseExactMatchExact match only
Doesn't have thisNotContainsNOT

Logic Combinators

NeedUseExample
All must matchwhere arrayA AND B AND C
Any can matchIncludes or whereGroupsA OR B OR C
Complex logicwhereGroups(A AND B) OR (C AND D)
Exclude resultsinclude: falseNOT A

Support

For questions about filters or help with complex queries:

Need more help? Reach out to our support team via 24/5 live chat.