Filters
Most Finance API collections endpoints support filtering based on one or more fields. You can use filters to return a subset of results that you’re interested in. They’ll usually make your response quicker by reducing the amount of data that’s sent in the response.
No filter
/finance/gifts
Single filter
/finance/gifts?filter[company]=UWGBY
Multiple filters
/finance/gifts?filter[company]=UWGBY&filter[giftType]=Donor_Direct
Filters Available
Different resources support filtering on different attributes. See the endpoints documentation for details about what’s available on each resource endpoint. If you choose an attribute that cannot be filtered on, you will get an error message.
Some endpoints mention supporting “new-style” querying, which means you can filter on every attribute listed in the attributes section of a resource by default, rather than filtering on each attribute having to be explicitly enabled like with “old-style” querying. With new-style querying, you can also use every special operator applicable for an attribute’s data type in any combination by default. Details on how exactly this works are provided below.
If an endpoint uses new-style querying, it is using our newer, more powerful filter parser and query builder, designed to be more flexible, maintainable, and powerful. Eventually, all endpoints will be moved to new-style querying, though with the amount of endpoints in the Finance API, this will take some time.
Accent & Case Neutrality
When filtering on strings, matches are always done in an accent- and case-agnostic manner. For more information on how this works, check out the specification for the Unicode Collation Algorithm (version 9.0.0). In general, it can be thought of as a language-aware accent- and case-normalizing algorithm suitable for a wide array of Unicode input, including canonically equivalent characters constructed with different code point sequences, which is important as Workday has no character limitations and there are accented characters in our data, alongside symbols like © and ™.
This behavior is the same for both old-style and new-style querying.
Multiple Values
If you want to match against multiple values, you can do so by separating their values using commas. For example, if you wanted to find all internalServiceProviders having one of five different funds, you could do so with this query:
/finance/internalServiceProviders?filter[fundId]=FD0100,FD0200,FD0300,FD0400,FD0500
On endpoints implementing old-style querying, this only works for string attributes, with non-string attributes usually returning error 400 messages. Endpoints implementing new-style querying can handle multiple values for all queryable data types.
Special Operators and Partial Matches
By default, filters work on exact matches only. For example, /finance/projects?filter[name]=UWMIL | Emergency Operations will only return projects with the exact name “UWMIL | Emergency Operations”.
Sometimes you don’t have the full value you’re looking for, or you want to get a range of results. To accomplish this, we support prepending special operators to parameter values to modify the way the value is interpreted.
| Operator | Description | Value type | Example |
|---|---|---|---|
STARTS_WITH: | Matches values that start with the string passed in | Strings | /finance/projects?filter[name]=STARTS_WITH:UWMIL |
ENDS_WITH: | Matches values that end with the string passed in | Strings | /finance/projects?filter[name]=ENDS_WITH:Operations |
CONTAINS: | Matches values that contain the string passed in anywhere within them | Strings | /finance/projects?filter[name]=CONTAINS:Emergency |
LESS_THAN: | Matches values that are strictly less than the value passed in. Will not return exact matches. | Dates, numbers, (new-style endpoints only:) strings | /finance/billingSchedules?filter[billingInstallments.amount]=LESS_THAN:5000.0 |
GREATER_THAN: | Matches values that are strictly greater than the value passed in. Will not return exact matches. | Dates, numbers, (new-style endpoints only:) strings | /finance/projects?filter[startDate]=GREATER_THAN:2025-04-01 |
In much the same way that the behavior of basic equality matching is governed by the Unicode Collation Algorithm, the behavior of GREATER_THAN and LESS_THAN on strings is also dependent upon the UCA. See “Accent & Case Neutrality” above for more information.
Note that, for endpoints that support old-style querying, you cannot use special operators in conjunction with multiple values. For example, /finance/ledgerAccounts?filter[name]=ENDS_WITH:Cash,Petty Cash,Investments may look like it is filtering for all ledgerAccounts whose name ends with “Cash”, “Petty Cash”, or “Investments”, or look for those whose name ends with “Cash” or exactly matches “Petty Cash” or “Investments”, but it will actually look for ledgerAccounts whose name exactly matches “ENDS_WITH:Cash”, “Petty Cash”, or “Investments”.
Endpoints supporting new-style queries do not suffer these limitations, and the way they behave is detailed below.
Combining Operators
On endpoints supporting new-style querying, you can add multiple special operators to the same filter query parameter instance to modify multiple values.
For instance, if you wanted to find all assets located in UW-Madison or UW-Milwaukee, you could do:
/finance/assets?filter[locationId]=STARTS_WITH:LCMSN,STARTS_WITH:LCMIL
Each value is evaluated in isolation, so a special operator on one value will not affect any others. If you wanted to find an asset whose manufacturer started with “Apple”, exactly matched “Dell”, or contained “electronics”, you could do so with this query:
/finance/assets?filter[manufacturer]=STARTS_WITH:Apple,Dell,CONTAINS:electronics
When using multiple operators within the same filter query parameter instance, it’s important to remember those values will be OR’d together. That is, this query will not search for just purchaseOrders issued in February 2026, as you might initially assume:
/finance/purchaseOrders?filter[issuedDate]=GREATER_THAN:2026-01-31,LESS_THAN:2026-03-01
Instead, this query will search for every purchaseOrder with a non-null issuedDate, because ORing them together creates a date range equivalent to (the first date representable on the Gregorian calendar <= issuedDate <= the end of the Gregorian calendar).
Logical AND vs OR
While multiple values on the same filter query parameter instance get combined with a logical OR, with new-style querying, separate filter query parameter instances get combined with a logical AND. For instance, if you wanted to find a billingSchedule that had a billingInstallment with an installmentDate in January of 2026, you could do so with this query:
/finance/billingSchedules?filter[billingInstallments.installmentDate]=GREATER_THAN:2025-12-31&filter[billingInstallments.installmentDate]=LESS_THAN:2026-02-01
Using this AND vs OR distinction, you can create more complex queries, like inclusive range operators. For instance, if you want to search for any purchaseOrder issued in February 2026 and you don’t want to think about leap years, you can take advantage of the ORing behavior to DIY a “greater than or equal” operator like so:
/finance/purchaseOrders?filter[issuedDate]=2026-02-01,GREATER_THAN:2026-02-01&filter[issuedDate]=LESS_THAN:2026-03-01
This also works with string values. For example, this query will find all isdLines related to DoIT public clouds:
/finance/isdLines?filter[itemDescription]=STARTS_WITH:UWMSN,CONTAINS:DoIT
&filter[itemDescription]=CONTAINS:AWS,CONTAINS:OCI,CONTAINS:GCP,CONTAINS:Oracle,CONTAINS:Google,CONTAINS:AMAZON
&filter[itemDescription]=CONTAINS:cloud
For endpoints that implement old-style querying, this behavior does not exist because, when multiple filter query parameter instances target the same attribute, only one instance will be used.
NULL Values
In the absence of a value, some strings attributes are given empty strings, while others are given null values. Since we aim to be a data aggregator rather than an interpreter, we pass these values through in their original form.
On endpoints supporting new-style querying, if you want to locate externalCustomers with an address whose line 2 is “” (empty string) or null, you can do so by providing a blank value:
/finance/externalCustomers?filter[address.addressLine2]=
You can combine this with other values (basic equality or special operators) as well. For instance, this query will find externalCustomers with an address whose line 2 is “” (empty string), null, starts with “Suite”, starts with “Ste”, or starts with “Unit”:
/finance/externalCustomers?filter[address.addressLine2]=,STARTS_WITH:Suite,STARTS_WITH:Ste,STARTS_WITH:Unit
For non-string attributes (dates, numbers, booleans, etc.), since “” is only possible for strings, blank values will only match null values. For example, this query will locate all internalServiceProviders that have the “active” attribute set to false or null:
/finance/internalServiceProviders?filter[active]=false,
On endpoints using old-style querying, the behavior for querying blank values is undefined. Some attributes may raise an error when attempting to do this, others may attempt to match something, but regardless, it probably won’t give you the results you want.
Filters Dictate Scope, Not Content
When querying attributes on nested resources, like internalCatalogs.id on internalServiceProviders and billingInstallments.amount on billingSchedules, the base resources returned are those which match your filter query parameters, but non-matching sub-resources are unaffected by them. To help illustrate the implications of this behavior, consider the following query:
/finance/externalCustomers?filter[active]=true
&filter[address.city]=Madison,Milwaukee,Oshkosh
&filter[address.stateCode]=WI
This query is looking for active external customers who have at least 1 address in Madison, Milwaukee, or Oshkosh, Wisconsin. This means:
- Hypothetical customer CUS0000001 has two addresses: one in Oshkosh, Nebraska and the other in Madison, Minnesota. They would not be returned by this query since neither address matches the stateCode filter.
- Hypothetical customer CUS0000002 has two addresses: one in Madison, Indiana and the other in Green Bay, Wisconsin. They also would not be returned by this query since neither address matches both the city and stateCode filters.
- Hypothetical customer CUS0000003 has three addresses: one in Madison, Indiana, another in Minneapolis, Minnesota, and the last in Oshkosh, Wisconsin. This customer will be returned, along with all three addresses.
The reason CUS0000003 will have both their matching and non-matching addresses returned is because the filters define the population, the scope of the query (the “who”); they do not dictate the content of the response (the “what”).
Filters affect which base/root resources get returned, but they do not affect what about those resources get returned because the Finance API returns the complete state of all matched resources, not a view of those resources tailored to the filters.
Examples
| Query | In English | What it means |
|---|---|---|
/finance/projects?filter[company]=UWMIL&filter[startDate]=GREATER_THAN:2025-06-30&filter[name]=CONTAINS:fpm | Return all projects associated with UWMIL that have a start date after June 30, 2025 and contain “fpm” (not case sensitive) in the name | Future facilities projects at Milwaukee |
/finance/billingSchedules?filter[billingInstallments.installmentDate]=GREATER_THAN:2025-03-31&filter[ | Return all billing schedules with at least one installment paid/scheduled after 2025-03-31 but before 2025-05-01 | Billing schedules with installments paid/scheduled for payment in April 2025 |