> ## Documentation Index
> Fetch the complete documentation index at: https://docs.enterspeed.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Query items

> The Query API is used to query items in an index.




## OpenAPI

````yaml /enterspeed/enterspeedv1Api.yaml post /v1/{indexAlias}
openapi: 3.0.0
info:
  version: 0.4.0
  title: API documentation
  description: >-
    The Enterspeed API are based on REST principles.


    Before you start you will need to [create an
    Enterspeed-account](https://app.enterspeed.com) and set up a tenant (a
    property for your website). Here you can create

    - A data source (provides you with an API key for the **Ingest API**).

    - An environment client (provides you with an API key for the **Delivery
    API** and **Query API**).

    - A domain (ensure the correct data gets fetched).


    🎉 Have fun using our API. Make sure to [contact
    us](https://www.enterspeed.com/contact) if you need any help. We're happy
    assist!
  x-logo:
    url: https://docs.enterspeed.com/img/logo.svg
    altText: Enterspeed Logo
  license:
    name: See Enterspeed Terms of service
    url: https://www.enterspeed.com/terms-of-service
servers:
  - url: https://api.enterspeed.com
    description: General API
security: []
tags:
  - name: Delivery
    description: >-
      The Delivery API is what you use to `GET` your data from Enterspeed to
      your frontend project. Before you can fetch your content from Enterspeed,
      you first need to create an **Environment client** which generates an API
      key. This is done under *Settings --> Environment settings*.


      You can find an example of how to fetch data [Umbraco & Next.js
      tutorial](https://docs.enterspeed.com/tutorials/umbraco-nextjs/fetching-data-in-nextjs).
  - name: Ingest
    description: >-
      The Ingest API is used to `POST` your current data sources into
      Enterspeed. Before you can start ingesting data, you'll need to create a
      **Data source** inside Enterspeed, which generates an API key. This is
      done under *Settings --> Data sources*.


      The Ingest API can also be used to `DELETE` already ingested data from
      Enterspeed.
  - name: Routes
    description: >-
      The Routes API is what you use to `GET` all available URL routes for a
      specific environment, which can be helpful for SSG (Static Site
      Generation) or creating a sitemap.


      Before you can fetch your routes from Enterspeed, you first need to create
      an **Environment client** which generates an API key. This is done under
      *Settings --> Environment settings*.


      **ℹ NOTE:** The `first` or `last` parameter is required and must be set
      between 100 - 500 (e.g. `first=250`). Both are not allowed at the same
      time.
  - name: Query
    description: >-
      The Query API is what you use to query items from your indexes.


      Before you can query your indexes from Enterspeed, you first need to
      create an **Environment client** which generates an API key. This is done
      under *Settings --> Environment settings*.
paths:
  /v1/{indexAlias}:
    servers:
      - url: https://query.enterspeed.com
        description: Query API
    post:
      tags:
        - Query
      summary: Query items
      description: |
        The Query API is used to query items in an index.
      operationId: queryContentPost
      parameters:
        - name: indexAlias
          in: path
          required: true
          description: |
            The alias of the index to be queried.
          schema:
            type: string
            example: productIndex
        - name: X-Api-Key
          required: true
          in: header
          description: Api key to validate your environment.
          schema:
            type: string
            example: environment-1637c4d0-e878-4738-b866-152106a4f88c
        - name: Content-Length
          required: true
          in: header
          description: >
            The length of the message body, in bytes (this header is
            automatically added by most clients).
          schema:
            type: number
      requestBody:
        description: >-
          The query object including things like filters, sorting and
          pagination.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QueryRequestBody'
      responses:
        '200':
          description: Valid request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/QueryResponse'
                type: object
        '400':
          description: >-
            Invalid request. Server responded but the request was in an invalid
            format.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Query400Response'
        '401':
          description: Unauthorized. Missing X-Api-Key header or the X-Api-Key is invalid.
        '403':
          description: Forbidden. The API key does not have the necessary permissions.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Query403Response'
components:
  schemas:
    QueryRequestBody:
      type: object
      description: >
        All root properties like, `filters`, `sort`, `pagination` and `facets`
        are optional.


        ### Filters

        `filters` are nested in one or two levels grouped in `and` or `or`.


        ```json

        "filters": {
          "and":  [
            {
              "field": "title",
              "operator": "equals",
              "value": "Enterspeed Hoodie"
            }
          ]
        }

        ```


        ```json

        "filters": {
          "or":  [
            {
              "field": "isInStock",
              "operator": "equals",
              "value": true
            },
            {
              "field": "allowPreorder",
              "operator": "equals",
              "value": true
            }
          ]
        }

        ```


        ```json

        "filters": {
          "and":  [
            {
              "field": "title",
              "operator": "equals",
              "value": "Enterspeed Hoodie"
            },
            {
              "or": [
                {
                  "field": "isInStock",
                  "operator": "equals",
                  "value": true
                },
                {
                  "field": "allowPreorder",
                  "operator": "equals",
                  "value": true
                }
              ]
            }
          ]
        }

        ```


        #### Operators


        **equals**

        ```json 

        {
          "field": "title",
          "operator": "equals",
          "value": "Enterspeed Hoodie",
          "caseInsensitive": true
        }

        ```


        **notEquals**

        ```json 

        {
          "field": "title",
          "operator": "notEquals",
          "value": "Enterspeed Hoodie",
          "caseInsensitive": true
        }

        ```


        **contains**


        Working on text or text list fields, it's possible to use wildcard
        annotations `*` if you want to query the fields only for specific words
        or sentences, no matter what comes before and after the phrase you
        search for. It's also possible to set if the search should be case
        insentitive by setting `caseInsensitive` to `true`.

        ```json 

        {
          "field": "title",
          "operator": "contains",
          "value": "*hoodie*",
          "caseInsensitive": true
        }

        ```


        Working on list fields on the other hand, the `contains` operator
        performs an equals on the list items, which will look for an exact match
        within the list. If working on text lists, it's also possible here to
        set if the search should be case insentitive by setting
        `caseInsensitive` to `true` as above.

        ```json 

        {
          "field": "categories",
          "operator": "contains",
          "value": "Hoodies",
          "caseInsensitive": true
        }

        ```


        **greaterThan**

        ```json 

        {
          "field": "price",
          "operator": "greaterThan",
          "value": 100
        }

        ```


        **greaterThanOrEquals**

        ```json 

        {
          "field": "price",
          "operator": "greaterThanOrEquals",
          "value": 100
        }

        ```


        **lessThan**

        ```json

        {
          "field": "price",
          "operator": "lessThan",
          "value": 100
        }

        ```


        **lessThanOrEquals**

        ```json

        {
          "field": "price",
          "operator": "lessThanOrEquals",
          "value": 100
        }

        ```


        **in**

        ```json

        {
          "field": "tag",
          "operator": "in",
          "value": ["shoes", "caps", "pants"],
        }

        ```


        ### Sorting

        `sort` is an array of objects defining the sort order. Each object
        defines the property to sort on and the direction. 


        If you have multiple sorting object the sorting will be in the order of
        the object. In the example below it would mean: first sort by
        `isInStock` in descending order and then by `title` in ascending order.


        #### Default values

        `field`: _updatedAt \

        `order`: desc


        For custom sorting, default `order` is `asc`.


        ```json

        "sort": [
          {
            "field": "isInStock",
            "order": "desc"
          },
          {
            "field": "title",
            "order": "asc"
          }
        ]

        ```


        ### Pagination

        `pagination` supports two modes: offset-based and token-based.


        #### Default values

        `page`: 0 \

        `pageSize`: 10


        #### Offset-based pagination

        Use `page` and `pageSize` to paginate by offset. The total number of
        reachable items is limited to 10.000 (`from + pageSize`). The maximum
        page size is 1.000. Use this method when you need to display the current
        page number, allow users to jump to a specific page, or navigate back to
        previous pages.


        ```json

        "pagination": {
          "page": 0,
          "pageSize": 20
        }

        ```


        #### Token-based pagination

        Use `nextPageToken` to paginate beyond the 10.000-item offset limit, or
        for more efficient iteration over large result sets. The token is
        returned in every response and is `null` when no further results exist.
        Pass it back in the next request to retrieve the next page. `page` is
        ignored when `nextPageToken` is provided. Use this method for
        integrations and bulk processing where you need to iterate the full
        result set — note that it does not expose the current page number or
        support navigating back to a previous page.


        **First request** — omit the token to get the first page:

        ```json

        "pagination": {
          "pageSize": 100
        }

        ```


        **Response** — includes `nextPageToken` alongside results:

        ```json

        {
          "totalResults": 5000,
          "results": [...],
          "nextPageToken": "WyIyMDI0LTAxLTAxIiwiYWJjMTIzIl0="
        }

        ```


        **Subsequent requests** — pass the token to get the next page:

        ```json

        "pagination": {
          "pageSize": 100,
          "nextPageToken": "WyIyMDI0LTAxLTAxIiwiYWJjMTIzIl0="
        }

        ```


        Repeat until `nextPageToken` is `null`.


        **Token scoping** — a `nextPageToken` is tied to the index it was issued
        for. Using it against a different index alias returns an `Invalid
        nextPageToken` error. Always use the token with the same index it came
        from.


        **Last page behaviour** — when the total number of results is an exact
        multiple of `pageSize`, the final page returns a full set of results
        with a non-null token. One additional request is needed to confirm there
        are no more results; that request returns an empty `results` array and a
        `null` token. This is expected — treat an empty response with `null`
        token as end-of-results, not an error.


        ### Aliases

        Using `aliases` in the query will return views for the provided schema
        aliases for each item in the result. The specific views returned for
        each item is the view created by the same source entity as the item. As
        views are returned, only schema aliases of full schemas are supported,
        as it's the only schema type that's creating views.


        This allows you to return different views for the same index. E.g. a
        productTile view or a productDetails view for a product index, whitout
        having to add all presentation data for both views to the index. You
        only need the data to filter and sort on.


        ```json

        "aliases": ["productTile"]

        ```


        ### Facets

        Using `facets` in the query allows for aggregated groupings of fields
        values used for facets. 


        A facet is requested by a required `field` name to do the aggregation
        on. There are options to add an optional `name` for the facet, and an
        optional `size` field to adjust the number of aggregated values returned
        - the size defaults to 10 and has a maximum of 100. The returned
        aggregated values are sorted by highest count first, i.e., requesting
        with a size of 5 would return the 5 facets with the highest count.


        All index schema types are supported for facet aggregation except the
        following: `object`, `integerRange`, `longRange`, `floatRange`,
        `doubleRange` and `dateRange`. 


        #### Default values

        `name`: The value of `field` \

        `size`: 10 


        ```json

        "facets": [
          {
            "name": "Categories",
            "field": "category",
            "size": 20
          },
          {
            "field": "isInStock"
          }
        ]

        ```
      example:
        filters:
          and:
            - field: title
              operator: contains
              value: '*hoodie*'
              caseInsensitive: true
            - or:
                - field: isInStock
                  operator: equals
                  value: true
                - field: allowPreorder
                  operator: equals
                  value: true
        aliases:
          - productTile
        facets:
          - name: Categories
            field: category
            size: 20
          - name: In Stock
            field: isInStock
        sort:
          - field: price
            order: asc
        pagination:
          page: 0
          pageSize: 20
    QueryResponse:
      type: object
      properties:
        status:
          type: number
          example: 0
        totalResults:
          type: number
          example: 200
          description: The total number of results matched by query.
        results:
          type: array
          description: |
            List of items from the index matched by the query provided.

            Built in fields are prefixed with underscore (`_`).
          items:
            type: object
            example:
              sku: p-5427
              name: Running shoe
              url: /products/running-shoe/
              _originId: p-5427
              _sourceGuid: 9f741916-19e3-4791-9ebd-701634ba9b75
              _updatedAt: '2025-01-07T08:43:15.7351089Z'
              _views:
                productTile:
                  sku: p-5427
                  name: Running shoe
                  url: /products/running-shoe/
                  image: /media/running-shoe.webp
                  shortDescription: My short description of the product
                  price: 199.99
        facets:
          type: array
          description: List of aggregated field values based on the requested facet fields.
          items:
            type: object
            example:
              name: Categories
              field: category
              groups:
                - value: Caps
                  count: 8
                - value: Hoodies
                  count: 2
              isValid: true
        nextPageToken:
          type: string
          nullable: true
          description: >-
            Continuation token for the next page of results. Pass this value in
            the `pagination.nextPageToken` field of the next request. `null`
            when no further results exist.
          example: WyIyMDI0LTAxLTAxIiwiYWJjMTIzIl0=
    Query400Response:
      type: object
      properties:
        message:
          type: string
          description: Erros message
          example: Query is not valid
        errors:
          type: array
          description: List of errors
          items:
            type: string
            example: 'Operator not implemented: equal'
        status:
          type: number
          example: 0
    Query403Response:
      type: object
      properties:
        error:
          type: string
          example: Forbidden

````