Query

View as Markdown

Query

A query narrows a list of entries, or of assets, to the items whose fields match the conditions you set. Use this class to

  • match field values with comparisons, value lists, patterns, and existence checks
  • filter entries by the entries their reference fields point to
  • combine conditions with $and and $or
  • sort, page, and run the request

query() takes one optional argument:

NameTypeDescription
queryObj{ [key: string]: any }Raw conditions to start with. Accepted by entry().query() only.

Get a Query from stack.contentType('<CONTENT_TYPE_UID>').entry().query() to filter entries, or from stack.asset().query() to filter assets. The package exports Query as a type only, so you can annotate a variable with it, but you get instances from these two calls. stack.taxonomy() returns a TaxonomyQuery, which extends Query. The Taxonomy class page covers it.

addParams

addParams merges several query parameters into the request at once.

NameTypeDescription
paramObj (required){ [key: string]: string | boolean | number }

Query parameter names mapped to their values.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • There is no client-side validation. addParams accepts any key, including keys that other methods set.
  • Errors surface on the find() call that follows, not on addParams(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. addParams merges the keys into the stored query parameters and makes no request. A key that already exists takes the new value.
  • addParams builds a new parameter object instead of changing the existing one. From that point, the query no longer shares its parameters with the Entries that created it. See Shared state on the Query class page.
  • The values become query parameters, not filter conditions. Use the filter methods, such as where, for conditions.

Example

Basic usage: set two parameters at once

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .exists('title')
    .addParams({ locale: 'en-us', include_count: true })
    .find();
  console.log(result.count, result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

and

and matches entries that satisfy all of the given queries.

NameTypeDescription
queries (required)Query[]

Queries whose conditions to combine with $and.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • There is no client-side validation. A call with no arguments compiles and sends an empty list.
    • On an entry query, the API ignores the empty list and returns every entry that the other conditions match.
    • On an asset query, the API rejects the empty list with status 400 and error_code 141. TypeScript rejects an argument that is not a Query.
  • Errors surface on the find() call that follows, not on and(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. and collects the conditions of each query into a list, stores it under the $and key, and makes no request. find sends the conditions as the query parameter.
  • A second and call replaces the first list, because the SDK stores it under one key. Pass every query in one call.
  • The list sits beside the query's other conditions. Field conditions on the outer query still apply to every result.
  • Only the sub-queries' conditions travel. Their content types and parameters play no part.
  • Known issue: In 5.x, two queries from one Entries object share their conditions. Build each sub-query from its own entry() call, as Shared state on the Query class page describes.
  • The queryOperator method does the same, with the operator passed as an argument.

Example

Basic usage: combine two conditions with $and

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const byTitle = stack.contentType('<CONTENT_TYPE_UID>').entry().query().equalTo('title', 'Home');
  const byDate = stack.contentType('<CONTENT_TYPE_UID>').entry().query().greaterThan('updated_at', '2026-01-01');
  const result = await stack.contentType('<CONTENT_TYPE_UID>').entry().query().and(byTitle, byDate).find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

Two conditions on one field: match a date range

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  // Two filters on one field in one query would replace each other, so combine two queries.
  const after = stack.contentType('<CONTENT_TYPE_UID>').entry().query().greaterThanOrEqualTo('updated_at', '2026-01-01');
  const before = stack.contentType('<CONTENT_TYPE_UID>').entry().query().lessThan('updated_at', '2026-07-01');
  const result = await stack.contentType('<CONTENT_TYPE_UID>').entry().query().and(after, before).find();
  console.log(result.entries?.length);
} catch (error: any) {
  console.error(error);
}

containedIn

containedIn matches entries whose field value equals one of the values in an array.

NameTypeDescription
key (required)string

UID or dotted path of the field to filter.

Default: Not applicable
value (required)(string | number | boolean)[]

Values the field may equal.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • Known issue: In 5.x, containedIn logs an error and drops the condition on invalid input. key must hold only letters, digits, underscores, periods, and hyphens, and value must be an array of strings, numbers, or booleans. Check both before you pass them.
  • TypeScript rejects a value of another type at compile time, so the runtime check matters only for a value typed as any.
  • An empty array passes the check. The API then matches no item.
  • Errors surface on the find() call that follows, not on containedIn(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. containedIn stores { <key>: { $in: <value> } } and makes no request. find sends the conditions as the query parameter.
  • A second filter on the same field replaces this one, because the SDK keys each condition on the field UID. See How conditions combine on the Query class page.
  • The notContainedIn method does the opposite.

Example

Basic usage: match entries with one of several titles

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .containedIn('title', ['Home', 'About', 'Contact'])
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

equalTo

equalTo matches entries whose field value equals the given value.

NameTypeDescription
key (required)string

UID or dotted path of the field to filter.

Default: Not applicable
value (required)string | number | boolean

Value to compare the field against.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • Known issue: In 5.x, equalTo logs an error and drops the condition when key holds a character other than letters, digits, underscores, periods, and hyphens. Check the field UID before you pass it.
  • Known issue: In 5.x, equalTo accepts boolean in its type, but logs an error and drops the condition for a true or false value. Use where(key, QueryOperation.EQUALS, true) for a boolean field.
  • Errors surface on the find() call that follows, not on equalTo(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. equalTo stores { <key>: <value> } and makes no request. find sends the conditions as the query parameter.
  • A second filter on the same field replaces this one, because the SDK keys each condition on the field UID. See How conditions combine on the Query class page.
  • The notEqualTo method does the opposite.

Example

Basic usage: match entries with an exact title

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .equalTo('title', 'Home')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

Boolean field: use where instead

import contentstack, { QueryOperation } from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  // equalTo('is_featured', true) compiles but drops the condition at runtime.
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .where('is_featured', QueryOperation.EQUALS, true)
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  console.error(error);
}

exists

exists matches entries that have the named field.

NameTypeDescription
key (required)string

UID or dotted path of the field to check.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • Known issue: In 5.x, exists logs an error and drops the condition when key holds a character other than letters, digits, underscores, periods, and hyphens. Check the field UID before you pass it.
  • Errors surface on the find() call that follows, not on exists(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. exists stores { <key>: { $exists: true } } and makes no request. find sends the conditions as the query parameter.
  • A second filter on the same field replaces this one, because the SDK keys each condition on the field UID. See How conditions combine on the Query class page.
  • The notExists method does the opposite.

Example

Basic usage: match entries that have a title

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .exists('title')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

find

find sends the request and returns the entries or assets that match the query.

NameTypeDescription
encodeboolean

Percent-encodes string values in the conditions first. See Limitations.

Default: false

Returns: Promise<FindResponse<T>>. The matching entries or assets.

Validation

  • There is no client-side validation. find sends whatever conditions and parameters the query holds.
  • find throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.
    • An unknown content type UID throws status 422 with error_code 118.
    • A network failure throws status 0, with the Node error code (for example ENOTFOUND) in error_code.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • One call sends one request and returns one page. The SDK does not iterate pages. See Pagination on the Query class page.
  • Which endpoint find calls depends on where the query came from.
    • From entry().query(): GET /content_types/{content_type_uid}/entries, with the results in entries.
    • From asset().query(): GET /assets, with the results in assets.
  • find returns the whole response body as a FindResponse<T>. Each key is optional, because the API includes only what you asked for. count appears when you chain includeCount.
  • find is generic. Pass an interface as T, for example one that extends the exported BaseEntry, to type each result. The SDK does not check the response against T.
  • find sends the conditions as the query parameter only when the query holds at least one. The parameters set by methods such as limit travel as separate query parameters.
  • encode acts only on the conditions.
  • When the Entries that created the query held variant UIDs, find sends the x-cs-variant-uid header, plus the branch header when the Entries also held a branch name.

Limitations

  • Does not return every match when you omit limit. For entries, the default page size is 100 entries, and the maximum page size is 250 entries. Chain the includeCount method and page with skip and limit.
  • Known issue: In 5.x, find(true) can return no results for a value that contains a space or a symbol such as & or /. It also breaks conditions that hold a list, such as containedIn, tags, and and or. Call find() instead.

Example

Basic usage: run a query against entries

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .equalTo('title', 'Home')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

Typed result: read matches into your own interface

import contentstack from '@contentstack/delivery-sdk';
import type { BaseEntry } from '@contentstack/delivery-sdk';

interface BlogPost extends BaseEntry {
  url: string;
}

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .exists('url')
    .find<BlogPost>();
  result.entries?.forEach((post) => console.log(post.title, post.url));
} catch (error: any) {
  console.error(error);
}

All parameters: leave encode off

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .equalTo('title', 'Home & Garden')
    .find(false);
  console.log(result.entries?.length);
} catch (error: any) {
  console.error(error);
}

Assets: run a query against assets

import contentstack, { QueryOperation } from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack.asset().query().where('content_type', QueryOperation.EQUALS, 'image/png').find();
  console.log(result.assets?.length);
} catch (error: any) {
  console.error(error);
}

getQuery

getQuery returns the filter conditions the query holds, in the JSON form that find sends.

Returns: object. The conditions the query holds.

Validation

  • There is no validation. getQuery takes no input and makes no request, so it cannot fail.

Behavior

  • Client-side only. getQuery reads local state and makes no request.
  • The declared return type is { [key: string]: any }. The object holds the conditions that find sends as the query parameter.
  • It returns the live object, not a copy. Changing the returned object changes the query.
  • It holds filter conditions only. Parameters such as limit, locale, or the typeahead term from search are not in it.
  • On a query from entry().query(), the object is the same one the Entries holds. See Shared state on the Query class page.

Example

Basic usage: inspect the conditions before sending the request

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

const query = stack
  .contentType('<CONTENT_TYPE_UID>')
  .entry()
  .query()
  .equalTo('title', 'Home')
  .greaterThanOrEqualTo('updated_at', '2026-01-01');

console.log(JSON.stringify(query.getQuery()));
// {"title":"Home","updated_at":{"$gte":"2026-01-01"}}

greaterThan

greaterThan matches entries whose field value is greater than the given value.

NameTypeDescription
key (required)string

UID or dotted path of the field to filter.

Default: Not applicable
value (required)string | number

Value to compare the field against.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • Known issue: In 5.x, greaterThan logs an error and drops the condition on invalid input. key must hold only letters, digits, underscores, periods, and hyphens, and value must be a string or a number. Check both before you pass them.
  • TypeScript rejects a value of another type at compile time.
  • Errors surface on the find() call that follows, not on greaterThan(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. greaterThan stores { <key>: { $gt: <value> } } and makes no request. find sends the conditions as the query parameter.
  • A second filter on the same field replaces this one, because the SDK keys each condition on the field UID. See How conditions combine on the Query class page.
  • greaterThan sends value unchanged, as a string or a number. The SDK does not convert a date string.
  • On a date field such as updated_at, the API compares an ISO 8601 string in date order. A date without a time, such as '2026-01-01', stands for midnight UTC at the start of that day.

Example

Basic usage: compare a date field

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .greaterThan('updated_at', '2026-01-01')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

Numeric field: compare a number

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .greaterThan('price', 10)
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  console.error(error);
}

greaterThanOrEqualTo

greaterThanOrEqualTo matches entries whose field value is greater than or equal to the given value.

NameTypeDescription
key (required)string

UID or dotted path of the field to filter.

Default: Not applicable
value (required)string | number

Value to compare the field against.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • Known issue: In 5.x, greaterThanOrEqualTo logs an error and drops the condition on invalid input. key must hold only letters, digits, underscores, periods, and hyphens, and value must be a string or a number. Check both before you pass them.
  • TypeScript rejects a value of another type at compile time.
  • Errors surface on the find() call that follows, not on greaterThanOrEqualTo(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. greaterThanOrEqualTo stores { <key>: { $gte: <value> } } and makes no request. find sends the conditions as the query parameter.
  • A second filter on the same field replaces this one, because the SDK keys each condition on the field UID. See How conditions combine on the Query class page.
  • greaterThanOrEqualTo sends value unchanged, as a string or a number. The SDK does not convert a date string.
  • On a date field such as updated_at, the API compares an ISO 8601 string in date order. A date without a time, such as '2026-01-01', stands for midnight UTC at the start of that day.

Example

Basic usage: compare a date field

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .greaterThanOrEqualTo('updated_at', '2026-01-01')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

Numeric field: compare a number

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .greaterThanOrEqualTo('price', 10)
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  console.error(error);
}

includeCount

includeCount adds the total number of matching items to the find response.

Returns: Query. The same query, for chaining.

Validation

  • Errors surface on the find() call that follows, not on includeCount(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. includeCount sets the include_count query parameter to 'true' and makes no request. find then returns a count key beside the results.
  • count is the total number of items that match the conditions, not the number on this page. Compare it with the length of entries or assets to find out whether more pages remain.
  • Calling it twice changes nothing. The SDK stores the flag under one key.

Example

Basic usage: count the matching entries

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .exists('title')
    .includeCount()
    .find();
  console.log('matches:', result.count, 'on this page:', result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

lessThan

lessThan matches entries whose field value is less than the given value.

NameTypeDescription
key (required)string

UID or dotted path of the field to filter.

Default: Not applicable
value (required)string | number

Value to compare the field against.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • Known issue: In 5.x, lessThan logs an error and drops the condition on invalid input. key must hold only letters, digits, underscores, periods, and hyphens, and value must be a string or a number. Check both before you pass them.
  • TypeScript rejects a value of another type at compile time.
  • Errors surface on the find() call that follows, not on lessThan(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. lessThan stores { <key>: { $lt: <value> } } and makes no request. find sends the conditions as the query parameter.
  • A second filter on the same field replaces this one, because the SDK keys each condition on the field UID. See How conditions combine on the Query class page.
  • lessThan sends value unchanged, as a string or a number. The SDK does not convert a date string.
  • On a date field such as updated_at, the API compares an ISO 8601 string in date order. A date without a time, such as '2026-01-01', stands for midnight UTC at the start of that day.

Example

Basic usage: compare a date field

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .lessThan('updated_at', '2026-01-01')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

Numeric field: compare a number

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .lessThan('price', 100)
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  console.error(error);
}

lessThanOrEqualTo

lessThanOrEqualTo matches entries whose field value is less than or equal to the given value.

NameTypeDescription
key (required)string

UID or dotted path of the field to filter.

Default: Not applicable
value (required)string | number

Value to compare the field against.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • Known issue: In 5.x, lessThanOrEqualTo logs an error and drops the condition on invalid input. key must hold only letters, digits, underscores, periods, and hyphens, and value must be a string or a number. Check both before you pass them.
  • TypeScript rejects a value of another type at compile time.
  • Errors surface on the find() call that follows, not on lessThanOrEqualTo(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. lessThanOrEqualTo stores { <key>: { $lte: <value> } } and makes no request. find sends the conditions as the query parameter.
  • A second filter on the same field replaces this one, because the SDK keys each condition on the field UID. See How conditions combine on the Query class page.
  • lessThanOrEqualTo sends value unchanged, as a string or a number. The SDK does not convert a date string.
  • On a date field such as updated_at, the API compares an ISO 8601 string in date order. A date without a time, such as '2026-01-01', stands for midnight UTC at the start of that day.

Example

Basic usage: compare a date field

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .lessThanOrEqualTo('updated_at', '2026-01-01')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

Numeric field: compare a number

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .lessThanOrEqualTo('price', 100)
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  console.error(error);
}

limit

limit caps the number of items the response contains.

NameTypeDescription
key (required)number

Maximum number of items to return.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • There is no client-side validation. The SDK sends zero, a negative number, or a fraction as given.
  • Errors surface on the find() call that follows, not on limit(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. limit sets the limit query parameter and makes no request. find sends it.
  • Omitting limit does not return every match. For entries, the default page size is 100 entries. See Pagination on the Query class page.
  • For entries, the API returns at most 250 per request. It caps a larger value at 250 and does not reject it.
  • Calling it twice replaces the first value. The paginate method also writes limit, so whichever runs last sets the value.

Example

Basic usage: return at most ten matching entries

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .exists('title')
    .limit(10)
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

notContainedIn

notContainedIn matches entries whose field value equals none of the values in an array.

NameTypeDescription
key (required)string

UID or dotted path of the field to filter.

Default: Not applicable
value (required)(string | number | boolean)[]

Values the field must not equal.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • Known issue: In 5.x, notContainedIn logs an error and drops the condition on invalid input. key must hold only letters, digits, underscores, periods, and hyphens, and value must be an array of strings, numbers, or booleans. Check both before you pass them.
  • TypeScript rejects a value of another type at compile time, so the runtime check matters only for a value typed as any.
  • An empty array passes the check. The API then excludes nothing, so every item matches.
  • Errors surface on the find() call that follows, not on notContainedIn(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. notContainedIn stores { <key>: { $nin: <value> } } and makes no request. find sends the conditions as the query parameter.
  • A second filter on the same field replaces this one, because the SDK keys each condition on the field UID. See How conditions combine on the Query class page.
  • The containedIn method does the opposite.

Example

Basic usage: leave out entries with certain titles

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .notContainedIn('title', ['Home', 'About'])
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

notEqualTo

notEqualTo matches entries whose field value differs from the given value.

NameTypeDescription
key (required)string

UID or dotted path of the field to filter.

Default: Not applicable
value (required)string | number | boolean

Value to compare the field against.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • Known issue: In 5.x, notEqualTo logs an error and drops the condition when key holds a character other than letters, digits, underscores, periods, and hyphens. Check the field UID before you pass it.
  • Known issue: In 5.x, notEqualTo accepts boolean in its type, but logs an error and drops the condition for a true or false value. Use where(key, QueryOperation.NOT_EQUALS, true) for a boolean field.
  • Errors surface on the find() call that follows, not on notEqualTo(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. notEqualTo stores { <key>: { $ne: <value> } } and makes no request. find sends the conditions as the query parameter.
  • A second filter on the same field replaces this one, because the SDK keys each condition on the field UID. See How conditions combine on the Query class page.
  • The equalTo method does the opposite.

Example

Basic usage: leave out entries with one title

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .notEqualTo('title', 'Home')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

Boolean field: use where instead

import contentstack, { QueryOperation } from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  // notEqualTo('is_featured', true) compiles but drops the condition at runtime.
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .where('is_featured', QueryOperation.NOT_EQUALS, true)
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  console.error(error);
}

notExists

notExists matches entries that do not have the named field.

NameTypeDescription
key (required)string

UID or dotted path of the field to check.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • Known issue: In 5.x, notExists logs an error and drops the condition when key holds a character other than letters, digits, underscores, periods, and hyphens. Check the field UID before you pass it.
  • Errors surface on the find() call that follows, not on notExists(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. notExists stores { <key>: { $exists: false } } and makes no request. find sends the conditions as the query parameter.
  • A second filter on the same field replaces this one, because the SDK keys each condition on the field UID. See How conditions combine on the Query class page.
  • The exists method does the opposite.

Example

Basic usage: match entries without a summary

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .notExists('summary')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

or

or matches entries that satisfy at least one of the given queries.

NameTypeDescription
queries (required)Query[]

Queries whose conditions to combine with $or.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • There is no client-side validation. A call with no arguments compiles and sends an empty list.
    • On an entry query, the API ignores the empty list and returns every entry that the other conditions match.
    • On an asset query, the API rejects the empty list with status 400 and error_code 141. TypeScript rejects an argument that is not a Query.
  • Errors surface on the find() call that follows, not on or(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. or collects the conditions of each query into a list, stores it under the $or key, and makes no request. find sends the conditions as the query parameter.
  • A second or call replaces the first list, because the SDK stores it under one key. Pass every query in one call.
  • The list sits beside the query's other conditions. Field conditions on the outer query still apply to every result.
  • Only the sub-queries' conditions travel. Their content types and parameters play no part.
  • Known issue: In 5.x, two queries from one Entries object share their conditions. Build each sub-query from its own entry() call, as Shared state on the Query class page describes.
  • The queryOperator method does the same, with the operator passed as an argument.

Example

Basic usage: combine two conditions with $or

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const byTitle = stack.contentType('<CONTENT_TYPE_UID>').entry().query().equalTo('title', 'Home');
  const byDate = stack.contentType('<CONTENT_TYPE_UID>').entry().query().greaterThan('updated_at', '2026-01-01');
  const result = await stack.contentType('<CONTENT_TYPE_UID>').entry().query().or(byTitle, byDate).find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

orderByAscending

orderByAscending sorts the matching items in ascending order of the named field.

NameTypeDescription
key (required)string

UID of the field to sort by.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • There is no client-side validation. The SDK sends an empty string or an unknown field UID as given.
  • Errors surface on the find() call that follows, not on orderByAscending(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. orderByAscending sets the asc query parameter to the field UID and makes no request. find sends it.
  • Without a sort method, the API applies its own default order.
  • orderByAscending does not clear a sort that the orderByDescending method set, which uses a different key. Call the removeParam method with 'desc' to drop it.

Limitations

  • Does not sort by more than one field. A second call replaces the first field, because the SDK stores it under one key.

Example

Basic usage: sort matching entries in ascending order

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .exists('title')
    .orderByAscending('updated_at')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

orderByDescending

orderByDescending sorts the matching items in descending order of the named field.

NameTypeDescription
key (required)string

UID of the field to sort by.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • There is no client-side validation. The SDK sends an empty string or an unknown field UID as given.
  • Errors surface on the find() call that follows, not on orderByDescending(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. orderByDescending sets the desc query parameter to the field UID and makes no request. find sends it.
  • Without a sort method, the API applies its own default order.
  • orderByDescending does not clear a sort that the orderByAscending method set, which uses a different key. Call the removeParam method with 'asc' to drop it.

Limitations

  • Does not sort by more than one field. A second call replaces the first field, because the SDK stores it under one key.

Example

Basic usage: sort matching entries in descending order

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .exists('title')
    .orderByDescending('updated_at')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

param

param sets one query parameter on the request.

NameTypeDescription
key (required)string

Name of the query parameter.

Default: Not applicable
value (required)string | number

Value to send for the parameter.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • There is no client-side validation. param accepts any key, including keys that other methods set.
  • Errors surface on the find() call that follows, not on param(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. param stores the value under key and makes no request. find sends it as a query parameter, not as a filter condition.
  • A key that already exists takes the new value, whichever method set it. For example, param('limit', 5) replaces an earlier limit(10).
  • Use param for an API parameter that has no method of its own. To set several keys at once, use the addParams method.

Example

Basic usage: set one query parameter

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .exists('title')
    .param('locale', 'en-us')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

queryOperator

queryOperator combines the conditions of several queries with the $and or $or operator that you choose.

NameTypeDescription
queryType (required)QueryOperator

QueryOperator.AND or QueryOperator.OR.

Default: Not applicable
queryObjects (required)Query[]

Queries whose conditions to combine.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • There is no client-side validation. A call with no queries compiles and sends an empty list.
    • On an entry query, the API ignores the empty list and returns every entry that the other conditions match.
    • On an asset query, the API rejects the empty list with status 400 and error_code 141.
  • Errors surface on the find() call that follows, not on queryOperator(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. queryOperator collects the conditions of each query into a list, stores it under the queryType key, and makes no request. find sends the conditions as the query parameter.
    • QueryOperator.AND writes $and, which matches entries that satisfy every query.
    • QueryOperator.OR writes $or, which matches entries that satisfy at least one query.
  • A second call with the same operator replaces the first list. $and and $or use different keys, so one of each can coexist.
  • queryOperator(QueryOperator.AND, ...) stores the same condition as the and method, and QueryOperator.OR the same as the or method.
  • Known issue: In 5.x, two queries from one Entries object share their conditions. Build each sub-query from its own entry() call, as Shared state on the Query class page describes.

Example

Basic usage: match entries that satisfy either condition

import contentstack, { QueryOperator } from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const home = stack.contentType('<CONTENT_TYPE_UID>').entry().query().equalTo('title', 'Home');
  const about = stack.contentType('<CONTENT_TYPE_UID>').entry().query().equalTo('title', 'About');
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .queryOperator(QueryOperator.OR, home, about)
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

All parameters: require every condition with AND

import contentstack, { QueryOperator } from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const titled = stack.contentType('<CONTENT_TYPE_UID>').entry().query().exists('title');
  const recent = stack.contentType('<CONTENT_TYPE_UID>').entry().query().greaterThan('updated_at', '2026-01-01');
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .queryOperator(QueryOperator.AND, titled, recent)
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  console.error(error);
}

referenceIn

referenceIn matches entries whose reference field points to entries that match a sub-query.

NameTypeDescription
key (required)string

UID of the reference field to filter.

Default: Not applicable
query (required)Query

Query whose conditions the referenced entries must match.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • Known issue: In 5.x, referenceIn logs an error and drops the condition when key holds a character other than letters, digits, underscores, periods, and hyphens. Check the field UID before you pass it.
  • The whereIn method throws on the same input instead.
  • The SDK does not check that query holds conditions. An empty sub-query sends an empty $in_query object.
  • Errors surface on the find() call that follows, not on referenceIn(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. referenceIn stores { <key>: { $in_query: <conditions of query> } } and makes no request. find sends the conditions as the query parameter.
  • Only the sub-query's conditions travel. Its content type, its parameters such as limit, and its variants play no part, and the SDK never sends a request for it.
  • referenceIn stores a reference to the sub-query's conditions, not a copy. A filter you add to the sub-query after the call still reaches the request.
  • A second filter on the same field replaces this one, because the SDK keys each condition on the field UID. See How conditions combine on the Query class page.
  • Known issue: In 5.x, two queries from one Entries object share their conditions. Build the sub-query from its own entry() call, as Shared state on the Query class page describes.
  • On an asset query, the API rejects the condition with status 400 and error_code 141.

Example

Basic usage: match entries whose author is a named author

import contentstack, { QueryOperation } from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  // The sub-query only supplies conditions. The SDK never sends a request for it.
  const authors = stack.contentType('author').entry().query().where('title', QueryOperation.EQUALS, 'John Doe');
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .referenceIn('author', authors)
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

referenceNotIn

referenceNotIn matches entries whose reference field points to entries that do not match a sub-query.

NameTypeDescription
key (required)string

UID of the reference field to filter.

Default: Not applicable
query (required)Query

Query whose conditions the referenced entries must not match.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • Known issue: In 5.x, referenceNotIn logs an error and drops the condition when key holds a character other than letters, digits, underscores, periods, and hyphens. Check the field UID before you pass it.
  • The whereNotIn method throws on the same input instead.
  • The SDK does not check that query holds conditions. An empty sub-query sends an empty $nin_query object.
  • Errors surface on the find() call that follows, not on referenceNotIn(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. referenceNotIn stores { <key>: { $nin_query: <conditions of query> } } and makes no request. find sends the conditions as the query parameter.
  • Only the sub-query's conditions travel. Its content type, its parameters such as limit, and its variants play no part, and the SDK never sends a request for it.
  • referenceNotIn stores a reference to the sub-query's conditions, not a copy. A filter you add to the sub-query after the call still reaches the request.
  • A second filter on the same field replaces this one, because the SDK keys each condition on the field UID. See How conditions combine on the Query class page.
  • Known issue: In 5.x, two queries from one Entries object share their conditions. Build the sub-query from its own entry() call, as Shared state on the Query class page describes.
  • On an asset query, the API rejects the condition with status 400 and error_code 141.

Example

Basic usage: match entries whose author is not a named author

import contentstack, { QueryOperation } from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  // The sub-query only supplies conditions. The SDK never sends a request for it.
  const authors = stack.contentType('author').entry().query().where('title', QueryOperation.EQUALS, 'John Doe');
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .referenceNotIn('author', authors)
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

regex

regex matches entries whose field value matches a regular expression.

NameTypeDescription
fieldUid (required)string

UID or dotted path of the field to match.

Default: Not applicable
regexPattern (required)string

Regular expression the field value must match.

Default: Not applicable
optionsstring

Regex options, such as i for case-insensitive.

Default: undefined

Returns: Query. The same query, for chaining.

Validation

  • Known issue: In 5.x, regex logs an error and drops the condition when fieldUid holds a character other than letters, digits, underscores, periods, and hyphens. Check the field UID before you pass it.
  • regex throws an Error at the call when regexPattern fails its check, because the SDK refuses to send a pattern it cannot validate. The check fails in two cases:
    • The pattern is empty or holds a character outside the allowed set: ASCII letters, digits, spaces, regex metacharacters, and common punctuation. Tabs, newlines, and non-ASCII letters such as é fail.
    • The pattern does not compile as a JavaScript regular expression, for example (unclosed.
  • The SDK does not check options.
  • API and network errors surface on the find() call that follows, not on regex(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. regex stores { <fieldUid>: { $regex: <regexPattern> } }, plus $options when you pass options, and makes no request. find sends the conditions as the query parameter.
  • The API runs the match. The SDK compiles the pattern only to check it.
  • A second filter on the same field replaces this one, because the SDK keys each condition on the field UID. See How conditions combine on the Query class page.

Limitations

  • Does not accept a pattern with non-ASCII letters, tabs, or newlines. Use the where method with QueryOperation.MATCHES instead, which stores the same condition without the pattern check.

Example

Basic usage: match titles that start with a word

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .regex('title', '^Home')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

All parameters: match case-insensitively

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .regex('title', '^home', 'i')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  console.error(error);
}

Error handling: an invalid pattern throws before any request

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

const query = stack.contentType('<CONTENT_TYPE_UID>').entry().query();
try {
  query.regex('title', '(unclosed');
} catch (error: any) {
  // Thrown by regex() itself, because the pattern does not compile.
  console.error('Invalid pattern:', error.message);
}

removeParam

removeParam deletes one query parameter from the request.

NameTypeDescription
key (required)string

Name of the query parameter to delete.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • There is no client-side validation. Removing a key that the chain never set does nothing.
  • Errors surface on the find() call that follows, not on removeParam(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. removeParam deletes key from the stored query parameters and makes no request.
  • removeParam clears parameters such as limit, include_count, or the typeahead term from search.

Limitations

  • Does not clear a filter condition, because the SDK stores conditions apart from parameters. Call entry() or asset() again to build a query without the condition.
  • Does not remove the environment parameter, because the stack configuration sends that value on every request. Create a second stack with another environment to read from a different environment.

Example

Basic usage: drop the search term before sending

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .search('home')
    .removeParam('typeahead')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

search adds a typeahead search term to the request.

NameTypeDescription
key (required)string

Search term, as one word.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • Known issue: In 5.x, search logs an error and drops a term that is empty or holds a character other than letters, digits, underscores, periods, and hyphens. It drops a multi-word term such as red shoes too. Use the regex method on a specific field instead.
  • Errors surface on the find() call that follows, not on search(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. search sets the typeahead query parameter and makes no request. find sends it.
  • The API matches the term anywhere inside the text fields of an entry, such as title, url, and other text fields, and ignores case. For example, search('ello') matches an entry titled Hello World.
  • The search does not cover tags, number fields, taxonomy terms, or the fields of referenced entries.
  • On an asset query without a locale, the API returns an asset once for each of its published locales. Pass a locale, for example with addParams({ locale: 'en-us' }), to get each asset once.
  • The term is a query parameter, not a condition, so getQuery does not show it, and the removeParam method clears it with removeParam('typeahead').
  • A second call replaces the first term.

Example

Basic usage: search for a one-word term

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .search('home')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

skip

skip sets the number of matching items the response leaves out before the first one it returns.

NameTypeDescription
key (required)number

Number of items to skip.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • There is no client-side validation. The SDK sends zero, a negative number, or a fraction as given.
  • Errors surface on the find() call that follows, not on skip(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. skip sets the skip query parameter and makes no request. find sends it.
  • Combine skip with the limit method to read one page at a time. For page n of size s, pass skip(n * s) and limit(s), counting pages from 0.
  • Calling it twice replaces the first value. The paginate method also writes skip, so whichever runs last sets the value.

Example

Basic usage: read the second page of ten

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .exists('title')
    .skip(10)
    .limit(10)
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

tags

tags filters entries by the tags assigned to them.

NameTypeDescription
values (required)(string | number | boolean)[]

The full tag list to match, in order.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • Known issue: In 5.x, tags logs an error and drops the condition when values is not an array of strings, numbers, or booleans. Pass an array of strings.
  • An empty array passes the check.
  • Errors surface on the find() call that follows, not on tags(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. tags stores the array under the tags key, as { tags: <values> }, and makes no request. find sends the conditions as the query parameter.
  • The API compares the whole tags array. An item matches only when its tags equal values exactly, in the same order.
    • For example, tags(['news']) does not match an entry tagged news and featured.
    • An empty array matches only items that have no tags.
  • A second call replaces the first array. Pass every tag in one call.
  • tags writes the same key as a field filter on tags. For example, containedIn('tags', [...]) replaces it, and it replaces that filter.

Limitations

  • Does not match items that carry any one of several tags. Use containedIn('tags', ['news', 'featured']) for that. See the containedIn method.

Example

Basic usage: filter entries by tags

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .tags(['featured', 'news'])
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

where

where adds a condition on a field, using any comparison operator or taxonomy operator.

NameTypeDescription
fieldUid (required)string

UID or dotted path of the field to filter.

Default: Not applicable
queryOperation (required)QueryOperation | TaxonomyQueryOperation

Comparison or taxonomy operator to apply.

Default: Not applicable
fields (required)string | string[] | number | number[] | object | boolean

Value to compare the field against.

Default: Not applicable
additionalDataobject

Extra operator options merged into the condition.

Default: undefined

Returns: Query. The same query, for chaining.

Validation

  • Known issue: In 5.x, where logs an error and drops the condition when fieldUid holds a character other than letters, digits, underscores, periods, and hyphens. Check the field UID before you pass it.
  • where does not check that fields suits the operator, for example an array for INCLUDES. The SDK sends a mismatched value as given.
  • Errors surface on the find() call that follows, not on where(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. where stores the condition and makes no request. find sends the conditions as the query parameter.
    • With QueryOperation.EQUALS, where stores the value itself, for example { title: 'Home' }. It ignores additionalData.
    • With any other operator, where stores an object, for example { price: { $lt: 100 } }, and merges additionalData into it.
  • A second filter on the same field replaces this one, because the SDK keys each condition on the field UID. See How conditions combine on the Query class page.
  • The table below lists the ten QueryOperation members.
MemberAPI operatorMatches when the field
EQUALSNone, the value itselfequals the value
NOT_EQUALS$nedoes not equal the value
INCLUDES$inequals one of the values in the array
EXCLUDES$ninequals none of the values in the array
IS_LESS_THAN$ltis less than the value
IS_LESS_THAN_OR_EQUAL$lteis less than or equal to the value
IS_GREATER_THAN$gtis greater than the value
IS_GREATER_THAN_OR_EQUAL$gteis greater than or equal to the value
EXISTS$existsexists, for true, or is absent, for false
MATCHES$regexmatches the regular expression
  • With a comparison operator on a date field such as updated_at, the API compares an ISO 8601 string in date order. A date without a time, such as '2026-01-01', stands for midnight UTC at the start of that day.
  • The table below lists the four TaxonomyQueryOperation members. Each takes the field path taxonomies.<TAXONOMY_UID> as fieldUid and a term UID as fields.
MemberAPI operatorMatches entries tagged with
ABOVE$abovean ancestor of the term, excluding the term
BELOW$belowa descendant of the term, excluding the term
EQ_ABOVE$eq_abovethe term or one of its ancestors
EQ_BELOW$eq_belowthe term or one of its descendants
  • Pass { levels: <number> } as additionalData to set the number of hierarchy levels a taxonomy operator covers. Without it, the API covers up to 10 levels.
  • The taxonomy operators also filter entries across content types on the TaxonomyQuery that stack.taxonomy() returns. See the Taxonomy class page.
  • The equalTo, lessThan, containedIn, and similar methods each cover one operator with a typed value.

Example

Basic usage: match entries with an exact title

import contentstack, { QueryOperation } from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .where('title', QueryOperation.EQUALS, 'Home')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

Comparison: match entries updated after a date

import contentstack, { QueryOperation } from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .where('updated_at', QueryOperation.IS_GREATER_THAN, '2026-01-01')
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  console.error(error);
}

All parameters: pass a regex option through additionalData

import contentstack, { QueryOperation } from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  // additionalData merges into the condition: { title: { $regex: '^home', $options: 'i' } }
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .where('title', QueryOperation.MATCHES, '^home', { $options: 'i' })
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  console.error(error);
}

Taxonomy: match entries tagged with a term or its children

import contentstack, { TaxonomyQueryOperation } from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .where('taxonomies.<TAXONOMY_UID>', TaxonomyQueryOperation.EQ_BELOW, '<TERM_UID>', { levels: 2 })
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  console.error(error);
}

Assets: match assets by MIME type

import contentstack, { QueryOperation } from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  const result = await stack.asset().query().where('content_type', QueryOperation.EQUALS, 'image/png').find();
  console.log(result.assets?.length);
} catch (error: any) {
  console.error(error);
}

whereIn

whereIn matches entries whose reference field points to entries that match a sub-query.

NameTypeDescription
referenceUid (required)string

UID of the reference field to filter.

Default: Not applicable
queryInstance (required)Query

Query whose conditions the referenced entries must match.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • whereIn throws an Error at the call when referenceUid contains a character other than letters, digits, underscores, periods, and hyphens. Unlike most filters, it does not log and continue. The referenceIn method logs instead.
  • The SDK does not check that queryInstance holds conditions. An empty sub-query sends an empty $in_query object.
  • API and network errors surface on the find() call that follows, not on whereIn(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. whereIn stores { <referenceUid>: { $in_query: <conditions of queryInstance> } } and makes no request. find sends the conditions as the query parameter.
  • Only the sub-query's conditions travel. Its content type, its parameters such as limit, and its variants play no part, and the SDK never sends a request for it.
  • whereIn stores a reference to the sub-query's conditions, not a copy. A filter you add to the sub-query after the call still reaches the request.
  • A second filter on the same field replaces this one, because the SDK keys each condition on the field UID. See How conditions combine on the Query class page.
  • Known issue: In 5.x, two queries from one Entries object share their conditions. Build the sub-query from its own entry() call, as Shared state on the Query class page describes.
  • On an asset query, the API rejects the condition with status 400 and error_code 141.

Example

Basic usage: match entries whose author is a named author

import contentstack, { QueryOperation } from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  // The sub-query only supplies conditions. The SDK never sends a request for it.
  const authors = stack.contentType('author').entry().query().where('title', QueryOperation.EQUALS, 'John Doe');
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .whereIn('author', authors)
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

Error handling: an invalid reference field UID throws before any request

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

const authors = stack.contentType('author').entry().query().exists('title');
try {
  stack.contentType('<CONTENT_TYPE_UID>').entry().query().whereIn('author name', authors);
} catch (error: any) {
  // Thrown by whereIn() itself, because the UID contains a space.
  console.error('Invalid reference field UID:', error.message);
}

whereNotIn

whereNotIn matches entries whose reference field points to entries that do not match a sub-query.

NameTypeDescription
referenceUid (required)string

UID of the reference field to filter.

Default: Not applicable
queryInstance (required)Query

Query whose conditions the referenced entries must not match.

Default: Not applicable

Returns: Query. The same query, for chaining.

Validation

  • whereNotIn throws an Error at the call when referenceUid contains a character other than letters, digits, underscores, periods, and hyphens. Unlike most filters, it does not log and continue. The referenceNotIn method logs instead.
  • The SDK does not check that queryInstance holds conditions. An empty sub-query sends an empty $nin_query object.
  • API and network errors surface on the find() call that follows, not on whereNotIn(). find() throws an APIError when the request fails, carrying the HTTP status, the API error_code, and the error_message.

Additional Resource Refer to Delivery API Errors for the full error code list.

Behavior

  • Client-side only. whereNotIn stores { <referenceUid>: { $nin_query: <conditions of queryInstance> } } and makes no request. find sends the conditions as the query parameter.
  • Only the sub-query's conditions travel. Its content type, its parameters such as limit, and its variants play no part, and the SDK never sends a request for it.
  • whereNotIn stores a reference to the sub-query's conditions, not a copy. A filter you add to the sub-query after the call still reaches the request.
  • A second filter on the same field replaces this one, because the SDK keys each condition on the field UID. See How conditions combine on the Query class page.
  • Known issue: In 5.x, two queries from one Entries object share their conditions. Build the sub-query from its own entry() call, as Shared state on the Query class page describes.
  • On an asset query, the API rejects the condition with status 400 and error_code 141.

Example

Basic usage: match entries whose author is not a named author

import contentstack, { QueryOperation } from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

try {
  // The sub-query only supplies conditions. The SDK never sends a request for it.
  const authors = stack.contentType('author').entry().query().where('title', QueryOperation.EQUALS, 'John Doe');
  const result = await stack
    .contentType('<CONTENT_TYPE_UID>')
    .entry()
    .query()
    .whereNotIn('author', authors)
    .find();
  console.log(result.entries?.length);
} catch (error: any) {
  // Thrown for API rejections and network failures
  console.error('Request failed:', error.status, error.error_code, error.error_message);
}

Error handling: an invalid reference field UID throws before any request

import contentstack from '@contentstack/delivery-sdk';

const stack = contentstack.stack({
  apiKey: '<API_KEY>',
  deliveryToken: '<DELIVERY_TOKEN>',
  environment: '<ENVIRONMENT>',
});

const authors = stack.contentType('author').entry().query().exists('title');
try {
  stack.contentType('<CONTENT_TYPE_UID>').entry().query().whereNotIn('author name', authors);
} catch (error: any) {
  // Thrown by whereNotIn() itself, because the UID contains a space.
  console.error('Invalid reference field UID:', error.message);
}