Search Filters

The Search Publications endpoint accepts a ?filters query parameter with a JSON-encoded query DSL for filtering documents by metadata and system fields.

Filter Fields

System fields

These fields come from the document's systemdata and are available for all documents.

PropertyType
documentIdlong
contentTypekeyword
firstPublicationDatedate
lastPublicationDatedate
significantPublicationDatedate
visiblePublicationDatedate

Publish control

Embargo fields exposed from internal editorial workflows. Only present on documents that use the embargo feature.

PropertyType
publishControl.embargo.enforcedboolean
publishControl.embargo.untildate

Statistics

Internally measured document statistics.

PropertyType
statistics.characterCountinteger
statistics.componentCount.*integer

Metadata fields

metadata.* covers all user-configured metadata properties. These are the fields you define in your project configuration. Metadata fields are the most common filter target for customer-specific use cases — filtering articles by topic, language, content classification, or any other custom property.

To be filterable, a metadata field needs two things:

  1. The plugin must support indexing (most do — see the table below)
  2. The field must have index: true set in the content type's metadata configuration

The filter key is metadata.<handle> for simple-value plugins, or metadata.<handle>.<key> for plugins that store objects with nested indexed properties.

Common plugins and their index types

PluginStoresIndex typeFilter key example
li-textstringkeyword, textmetadata.title
li-booleanbooleanbooleanmetadata.news
li-enumstringkeyword, textmetadata.status
li-integernumberintegermetadata.priority
li-datetimeISO date stringdatemetadata.deadline
li-dateISO date stringdatemetadata.publishDate
li-language{locale, ...}keywordmetadata.language.locale
li-category{id, path}keywordmetadata.category.id
li-document-reference{reference: {id}}keywordmetadata.author.reference.id
li-document-references{references: [{id}]}keywordmetadata.related.references.id
li-string-liststring arraykeyword, textmetadata.tags

Some plugins index the same value as both keyword (for exact match filtering) and text (for full-text search). The keyword type is used when filtering, while text is used when a ?search term matches against indexed metadata.

For the full list of plugin capabilities, consult your project configuration reference.

When querying a metadata property that stores an object, always use the key of a leaf node (e.g. metadata.teaserImage.mediaId), because only the indexed sub-properties are filterable, not the parent object itself.

Supported query capabilities by type

The index type of each field determines which query capabilities are supported:

TypeTermRangeExistsSort
keywordyesyesyesyes
integeryesyesyesyes
floatyesyesyesyes
doubleyesyesyesyes
longyesyesyesyes
dateyesyesyesyes
booleanyesyes

Query Expressions

Term

Exact match comparison. Some type coercion may be applied.

{
  key: 'metadata.title',
  term: 'My Title'
}

An array can be provided as the term value, which behaves like an OR:

{
  key: 'metadata.language.locale',
  term: ['de', 'fr']
}

Range

Search within a range. Operators gt, gte, lt, lte can be combined.

{
  key: 'metadata.count',
  range: {gt: 1, lt: 5}
}

Exists

Check if a property has been set.

{
  key: 'metadata.teaserImage.mediaId',
  exists: true
}

Logical Operators

Logical operators group queries and override the default AND behaviour of the top-level array. Operator values can be an object or an array containing other operators or query expressions.

AND

All conditions must be met.

{
  and: [
    {key: 'metadata.news', term: true},
    {key: 'metadata.teaserImage.mediaId', exists: false}
  ]
}

OR

Any condition can be met.

{
  or: [
    {key: 'metadata.image.mediaId', exists: true},
    {key: 'metadata.teaserImage.mediaId', exists: true}
  ]
}

NOT

Negates the expression. To negate multiple conditions, nest another logical operator within.

{
  not: {key: 'metadata.language.locale', term: 'de'}
}
{
  not: {
    or: [
      {key: 'metadata.news', term: false},
      {key: 'metadata.language.locale', term: 'fr'}
    ]
  }
}

Full Example

Combining logical operators and query expressions into a more complex query:

const filters = JSON.stringify({
  or: [
    {
      and: [
        {key: 'metadata.count', range: {lte: 2}},
        {key: 'metadata.bool', exists: true},
        {not: {key: 'metadata.title', term: 'My Title'}}
      ]
    },
    {key: 'metadata.count', term: 3}
  ]
})

const response = await fetch(
  `https://server.livingdocs.io/api/2026-01/publications/search?filters=${filters}`,
  {headers: {Authorization: 'Bearer ey1234'}}
)
const {results} = await response.json()

Sort Fields

The ?sort parameter accepts a comma-separated list of fields. Prefix with - to reverse the order (e.g. -sortDate,documentId).

Valid sort fields:

  • relevance (only effective with a ?search term)
  • sortDate (default, descending)
  • documentId
  • contentType
  • firstPublicationDate
  • lastPublicationDate
  • significantPublicationDate
  • visiblePublicationDate
  • metadata.*
  • publishControl.embargo.until

Documents without an indexed value for the sort field appear at the end of the results.

Using Filters with curl

filters=$(cat <<'EOF' | jq -c
{
  "key": "metadata.language.locale",
  "term": "de"
}
EOF
)

curl -s "https://server.livingdocs.io/api/2026-01/publications/search?filters=$filters" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
⌘ K to search