1. U4 ERPx
  2. API Reference
  3. ObjectAPI
  4. Horizontal Filtering

Horizontal Filtering

Filtering the number of returned documents

Introduction

It is a good practice to ensure that only the absolutely required documents are being requested. This can be achieved by providing an expression with the filter query parameter. The expression syntax is similar to what OData uses.

Using properties in expressions

Simple properties

For basic fields, reference them directly by name:

customerName eq 'Coffee & Cream Pottery'
maxCreditDays gt 30
isActive eq true

In the Enterprise Documents context, we can have:

TypeExample
Simple properties{ "customerName": "Marceli Gierszon", "customerId": "090909" }
Nested objects{ "invoice": { "currencyCode": "EUR", "hasFixedCurrency": true } }
Array of objects{ "contactPoints": [{ "contactPointType": "1", "address": { "countryCode": "NL" } }] }

When referencing these properties in a filter expression, use:

  • Access nested properties with the path separator /:
invoice/currencyCode eq 'EUR'
  • Filter arrays with lambda operators:
contactPoints/any(c: c/address/countryCode eq 'NL')

Operators and functions

Below is a quick reference for commonly used operators and functions in filter expressions:

CategoryOperator/FunctionDescriptionExample
ComparisoneqEqual tocustomerName eq 'Marceli Gierszon'
neNot equal tocountryCode ne 'GB'
gtGreater thaninvoice/maxCreditDays gt 30
geGreater or equal toinvoice/maxCreditDays ge 30
ltLess thaninvoice/maxCreditDays lt 30
leLess than or equal toinvoice/creditLimit le 100000.0
LogicalandLogical ANDcountryCode eq 'GB' and customerGroupId eq '1'
orLogical ORcountryCode eq 'GB' or customerGroupId eq '1'
notLogical NOTnot (countryCode eq 'GB')
Stringcontains(field, value)Contains substringcontains(customerName, 'Giers')
startswith(field, value)Starts with substringstartswith(customerName, 'Marceli')
endswith(field, value)Ends with substringendswith(customerName, 'Gierszon')
length(field)String lengthlength(customerName) gt 5
indexof(field, value)Index of substringindexof(customerName, 'celi') eq 4
substring(field, s, l)Extract substringsubstring(customerName, 1, 3) eq 'ohn'
trim(field)Remove whitespacetrim(customerName) eq 'Marceli Gierszon'
Date/Timeyear(field)Extract yearyear(lastUpdated/updatedAt) eq 2025
month(field)Extract monthmonth(lastUpdated/updatedAt) eq 8
day(field)Extract dayday(lastUpdated/updatedAt) eq 2
hour(field)Extract hourhour(lastUpdated/updatedAt) ge 11
minute(field)Extract minuteminute(lastUpdated/updatedAt) lt 24
second(field)Extract secondsecond(lastUpdated/updatedAt) gt 0
date(field)Date partdate(lastUpdated/updatedAt) eq 2025-08-07
time(field)Time parttime(lastUpdated/updatedAt) gt 14:30:00
Mathround(field)Round numberround(price) eq 100
floor(field)Round downfloor(average) eq 85
ceiling(field)Round upceiling(score) le 100
Collectionany(var: cond)At least one element matchescontactPoints/any(c: c/address/countryCode eq 'NL')
all(var: cond)All elements matchcontactPoints/all(c: c/address/countryCode eq 'NL')
Specialin1Matches one of the itemscountryCode in ('GB', 'NL')

Combining Multiple Conditions Using Parentheses

(countryCode eq 'GB' or countryCode eq 'NL') and customerGroupId eq 'X1'

Complex Array Filtering

The example below requests Customers which have a related value with attributeId A21 and value 10.

curl -v "https://unit4-api-address/v1/objects/customers\
        ?companyId=EN\
        &select=companyId,customerId,aliasName,relatedValues(relationName,relatedValue(*))\
        &filter=relatedValues/any(e:e/relatedValue/attributeId eq 'A21' and e/relatedValue/dimValue eq '10')\
        &orderBy=aliasName desc" \
    -H "Authorization: Bearer YOUR_TOKEN_HERE" \
    -H "Accept-Encoding: gzip" \
    -H "Accept: application/schema+json"

Error messages

In case of an error in the filter expression, an HTTP 400 response code is returned in the format:

{
  "code": 2147483647,
  "message": "string"
}

Commonly encountered errors

Wrong property reference in the expression
{
    "code": 1020,
    "message": "Could not find a property named 'crreditLimit' on type 'U4ERP.Objects.Customer.Invoice'."
}
Filter function incorrectly used due to non-matching argument types
{
    "code": 1020,
    "message": "No function signature for the function with name 'length' matches the specified arguments. The function signatures considered are: length(Edm.String Nullable=true)."
}
On arrays, we can only use the any or all operators

There will be an attempt to cast the array to an entity, but that will fail.

contactPoint.address/countryCode eq 'NL'
{
    "code": 1020,
    "message": "The child type 'contactPoint.address' in a cast was not an entity type. Casts can only be performed on entity types."
}

Tips for Writing Effective Filters

  1. Use parentheses for complex logic: (A and B) or (C and D)
  2. Quote string values: Use single quotes for string literals
  3. Date formats: Use ISO 8601 format for dates: 2024-12-25T14:30:00Z
  4. Property validation: Always check the metadata to confirm available properties and their types