---
title: "Using Advanced Queries in ServiceNow API"
url: "https://docs.noreja.com/en/article/using-advanced-queries-in-servicenow-api"
language: "en"
last_updated: "2026-03-08T19:00:27.106Z"
---

# Using Advanced Queries in ServiceNow API

Using advanced queries in the ServiceNow REST API allows you to precisely control which records are retrieved, filtered, and processed by external tools. Through the encoded query syntax in sysparm_query, you can replicate complex SQL-like WHERE logic—including AND/OR combinations, grouped conditions, relative date filters, text searches, and list operations. Mastering operators such as ^, ^OR, and ^NQ, along with pagination and display parameters, enables high-performance, clean, and scalable integrations between ServiceNow and analytics platforms like Noreja.

## ServiceNow “WHERE” basics (Encoded Query)

In ServiceNow’s REST Table API, you pass a **single string** in `sysparm_query` that acts like a SQL WHERE clause. It’s called an **encoded query**.

**Field** + **operator** + **value**, joined by **carets**:

`fieldOPvalue^field2OPvalue2...`

**AND** is `^`

**OR** is `^OR`

**Group ORs** / separate disjoint clauses with `^NQ`

You’ll typically also use helpful params like:

`sysparm_fields=...` (select columns)

`sysparm_limit=...` (row limit)

`sysparm_display_value=true` (return display values)

`sysparm_exclude_reference_link=true` (cleaner refs)

`sysparm_query_no_domain=true` (if you need to ignore domain separation)

## Operator cheat-sheet

| Purpose | Encoded operator | Example |
| --- | --- | --- |
| Equals | `=` | `state=2` |
| Not equals | `!=` | `state!=6` |
| Greater / Less | `>`, `<`, `>=`, `<=` | `priority<=2` |
| In list | `IN` (comma-sep) | `priorityIN1,2,3` |
| Not in list | `NOT IN` | `assignment_groupNOT INd625dc6c6fdd...` |
| Contains (case-insens.) | `LIKE` or `CONTAINS` | `short_descriptionLIKEemail` |
| Starts with | `STARTSWITH` | `caller_id.emailSTARTSWITHjohn` |
| Ends with | `ENDSWITH` | `u_reference_idENDSWITH-2025` |
| Empty / Not empty | `ISEMPTY`, `ISNOTEMPTY` | `closed_atISEMPTY` |
| Instance of (class) | `INSTANCEOF` | `sys_class_nameINSTANCEOFtask` |
| Between dates (via two ops) | `>=` and `<=` | `sys_updated_on>=2025-08-01^sys_updated_on<=2025-08-23 23:59:59` |

Notes  
• `LIKE` and `CONTAINS` are commonly used interchangeably for substring matches.  
• Most text matching is case-insensitive.  
• Values with spaces/special chars should be URL-encoded in the final request.

## Building logic: AND, OR, grouping

### AND (`^`)

`active=true^priority<=2`

### OR (`^OR`)

`priority=1^ORpriority=2`

Tip: You can chain many `^OR...` pieces.

### Grouping with `^NQ`

`^NQ` starts a **new query clause** that’s OR’ed with the previous entire clause. It’s the trick for “(A AND B) OR (C AND D)”.

`(active=true^priority=1)^NQ(state=2^assignment_group=287ebd7da9fe198100f92cc8d1d2154e)`

Read as: `(active=true AND priority=1) OR (state=2 AND assignment_group=...)`.

## Text operations & “wildcards”

You don’t use `%` or `*` with `LIKE`; the operator itself implies partial match.

**Contains**: `short_descriptionLIKEemail`

**Starts with**: `u_ticket_idSTARTSWITHABC-`

**Ends with**: `u_ticket_idENDSWITH-42`

**Does not contain**: `short_descriptionDOESNOTCONTAINphish`

If you must literally match special characters (like `^` inside a value), URL-encode them in the request. Inside ServiceNow’s list filters, you might see escaping with `\`; for REST, rely on URL encoding.

## Dates & relative time

You can compare to absolute timestamps (in instance’s timezone) or use ServiceNow’s **relative date macros**:

### Absolute

`sys_updated_on>=2025-08-01 00:00:00^sys_updated_on<=2025-08-23 23:59:59`

### Relative (server-side JS macros)

`sys_updated_on>=javascript:gs.daysAgoStart(7)`

Common macros:

`gs.daysAgoStart(n)`, `gs.daysAgoEnd(n)`

`gs.beginningOfLastMonth()`, `gs.endOfLastMonth()`

`gs.hoursAgoStart(n)`, etc.

These are handy for “last 7 days”, “today”, “this month”, etc., without hardcoding dates.

More info on how to transform timestamps directly in Noreja can be found [here](https://docs.noreja.com/en/article/deep-dive-timestamp-formatting).

## Pagination, fields, and display values

**Limit**: `sysparm_limit=100` (default is often 10)

**Offset**: `sysparm_offset=0` (paginate yourself)

**Fields**: `sysparm_fields=number,short_description,priority,state`

**Display values**: `sysparm_display_value=true` to get human-friendly strings for references and choices.

## Grouped logic with `^OR` vs `^NQ`

### Using `^OR` (within one group)

“Priority 1 **OR** 2, **AND** active”

`priority=1^ORpriority=2^active=true` 

This is evaluated left-to-right with implicit ANDs between carets; `^OR` has lower precedence than the explicit grouping you can achieve with `^NQ`. In most real cases this behaves as intended.

### Using `^NQ` (between groups)

“(active **AND** priority 1) **OR** (state is On Hold **AND** updated last 7d)”

`active=true^priority=1^NQstate=3^sys_updated_on>=javascript:gs.daysAgoStart(7)`
