Skip to main content

Build filters correctly

A filter selects which records match a request. It does not grant access to records outside your application's permissions. Use the resource's public field names, such as firstName, rather than database or C# property names.

Combine conditions deliberately​

For contacts named Alex whose surname is Morgan, send one expression:

GET /jsonapi/contacts?filter=and(equals(firstName,'Alex'),equals(lastName,'Morgan'))

Use or(...) when either condition should match. Nest expressions for more complex criteria. Multiple filter values on the same resource are combined with OR, so use an explicit and(...) when every condition must hold.

Quote values, then encode the URL​

A literal apostrophe is doubled inside a quoted filter value:

equals(lastName,'O''Brien')

A null comparison uses the unquoted keyword null; 'null' is a string:

not(equals(email,null))

Keep syntax construction separate from URL encoding. This example fixes the field and operator, escapes only the value, then lets the URL API encode the complete expression:

const quoteValue = (value) => `'${String(value).replaceAll("'", "''")}'`;
const url = new URL(`${API_BASE_URL.replace(/\/$/, "")}/jsonapi/contacts`);
url.searchParams.set("filter", `equals(lastName,${quoteValue("O'Brien")})`);

Do not accept arbitrary field names, operators or whole filter expressions from an untrusted input. Use an allowlist appropriate to your integration.

A visible field may not support a query​

MyCRM defines capabilities per field. In the reviewed contact definition, firstName and lastName support filtering and sorting. dateOfBirth can be viewed, created and changed, but is not enabled for filtering or sorting. A schema's data type alone cannot tell you these capabilities.

An unsupported field or malformed expression is a request problem to correct; repeating it will not make it valid. Read the returned error details and troubleshooting guidance.

For the operator table, paging and field selection, return to query efficiently.