Search via the API

As a supplement to the CRUD endpoints for Documents, our JSON:API also provides search endpoints. With these endpoints, you can search semantically within your knowledge base and further refine the results with filters, facets, sorting, and pagination.

These search endpoints are intended for situations where it is not enough to retrieve a document by ID, but where you want to find relevant documents or document fragments based on a search query.

Authentication

To authorize HTTP requests to our system, we use a so-called long lived Bearer token.

Example of an Authorization header with a Bearer token:

Authorization: Bearer 31090db4198c2bf9f9a7d768bf6107a40f102d47534cb122b0
Authorization: Bearer 31090db4198c2bf9f9a7d768bf6107a40f102d47534cb122b0
Authorization: Bearer 31090db4198c2bf9f9a7d768bf6107a40f102d47534cb122b0

The endpoints are available per customer under their own subdomain, for example:

https://{klant}.vragen.ai/api/v1/
https://{klant}.vragen.ai/api/v1/
https://{klant}.vragen.ai/api/v1/

The API expects the following headers with every request:

Accept: application/vnd.api+json
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json

Search endpoints

There are two search endpoints available:

1. Search in documents

GET https://{klant}.vragen.ai/api/v1/documents/search
GET https://{klant}.vragen.ai/api/v1/documents/search
GET https://{klant}.vragen.ai/api/v1/documents/search

This endpoint returns search results at document level. Each result refers to a document from the knowledge base.

2. Search in document fragments

GET https://{klant}.vragen.ai/api/v1/document-chunks/search
GET https://{klant}.vragen.ai/api/v1/document-chunks/search
GET https://{klant}.vragen.ai/api/v1/document-chunks/search

This endpoint returns search results at chunk level. A chunk is a fragment of a document. This endpoint is useful when you want to receive more fine-grained search results than at full document level.

Although the source differs, both endpoints have the same request and response structure.

General request parameters

The following query parameters are supported:

query

Type: string
Optional

The natural-language search question or search term on which semantic search is performed.

Example:

?query=city hall opening hours
?query=city hall opening hours
?query=city hall opening hours

maxDistance

Type: number
Optional
Value: between 0 and 1

This lets you limit the maximum semantic distance of results. A lower value makes the search stricter.

Example:

?query=permit&maxDistance=0.4
?query=permit&maxDistance=0.4
?query=permit&maxDistance=0.4

page[offset]

Type: integer
Optional
Default: 0

The number of results to skip.

page[limit]

Type: integer
Optional
Default: determined by the platform

The maximum number of results to return.

Example:

?query=leave&page[offset]=0&page[limit]=25
?query=leave&page[offset]=0&page[limit]=25
?query=leave&page[offset]=0&page[limit]=25

sort

Type: string
Optional

Sort fields are specified comma-separated. Use:

  • veldnaam for ascending sort

  • -veldnaam for descending sort

  • +veldnaam explicitly for ascending sort

Example:

?query=annual report&sort=-date,title
?query=annual report&sort=-date,title
?query=annual report&sort=-date,title

Which sortable fields are available depends on the fields configured for the knowledge base.

fields[...]

Type: sparse fieldset
Optional

This lets you limit the number of response fields.

For documents/search you use, for example:

fields[documents]=id,url,title,summary
fields[documents]=id,url,title,summary
fields[documents]=id,url,title,summary

For document-chunks/search you use, for example:

fields[document-chunks]=id,url,summary
fields[document-chunks]=id,url,summary
fields[document-chunks]=id,url,summary

You can also use the internal resource type directly:

fields[semantic-searchables]=id,url,title,summary
fields[semantic-searchables]=id,url,title,summary
fields[semantic-searchables]=id,url,title,summary

Note: the response internally uses the resource type semantic-searchables, but the API also accepts the aliases documents and document-chunks in fields[...] for these endpoints.

Filters

With filter, you can limit search results to documents or chunks that meet additional conditions.

The filters are passed as an array of objects. Each filter rule supports, among other things:

  • path: the name of the field you want to filter on

  • value: the value being searched for

  • operator: the comparison operator

  • id: optional, for grouped filters

  • parent: optional, to link filters to a group

  • tag or tags: optional, to label filters

Available filter operators:

  • =

  • !=

  • >

  • >=

  • <

  • <=

  • LIKE

  • IN

  • ALL

  • NOT IN

  • IS NULL

Boolean operators are available for filter groups:

  • AND

  • OR

Which path values can you use?

The available filter fields depend on how the customer's knowledge base is set up. In practice, this includes:

  • metadata fields from meta_data

  • knowledge scope fields

  • system fields, such as source

Note:

  • metadata keys are stored internally in snake_case

  • a metadata field such as publishDate therefore becomes publish_date, for example

Simple filter example

Search only within documents whose metadata author equals SWIS:

GET https://{klant}.vragen.ai/api/v1/documents/search?query=homepage&filter[0][path]=author&filter[0][operator]==&filter[0][value]=SWIS
GET https://{klant}.vragen.ai/api/v1/documents/search?query=homepage&filter[0][path]=author&filter[0][operator]==&filter[0][value]=SWIS
GET https://{klant}.vragen.ai/api/v1/documents/search?query=homepage&filter[0][path]=author&filter[0][operator]==&filter[0][value]=SWIS

Filter example with list values

Search within documents that fall into one of multiple categories:

GET https://{klant}.vragen.ai/api/v1/documents/search?query=policy&filter[0][path]=category&filter[0][operator]=IN&filter[0][value][]=policy&filter[0][value][]=news
GET https://{klant}.vragen.ai/api/v1/documents/search?query=policy&filter[0][path]=category&filter[0][operator]=IN&filter[0][value][]=policy&filter[0][value][]=news
GET https://{klant}.vragen.ai/api/v1/documents/search?query=policy&filter[0][path]=category&filter[0][operator]=IN&filter[0][value][]=policy&filter[0][value][]=news

Filter example with groups

Search for documents where:

  • source = website

  • AND (category = faq OR category = manual)

GET https://{klant}.vragen.ai/api/v1/documents/search?query=password&filter[0][id]=group_root&filter[0][operator]=AND&filter[1][path]=source&filter[1][operator]==&filter[1][value]=website&filter[2][id]=group_categories&filter[2][parent]=group_root&filter[2][operator]=OR&filter[3][parent]=group_categories&filter[3][path]=category&filter[3][operator]==&filter[3][value]=faq&filter[4][parent]=group_categories&filter[4][path]=category&filter[4][operator]==&filter[4][value]=manual
GET https://{klant}.vragen.ai/api/v1/documents/search?query=password&filter[0][id]=group_root&filter[0][operator]=AND&filter[1][path]=source&filter[1][operator]==&filter[1][value]=website&filter[2][id]=group_categories&filter[2][parent]=group_root&filter[2][operator]=OR&filter[3][parent]=group_categories&filter[3][path]=category&filter[3][operator]==&filter[3][value]=faq&filter[4][parent]=group_categories&filter[4][path]=category&filter[4][operator]==&filter[4][value]=manual
GET https://{klant}.vragen.ai/api/v1/documents/search?query=password&filter[0][id]=group_root&filter[0][operator]=AND&filter[1][path]=source&filter[1][operator]==&filter[1][value]=website&filter[2][id]=group_categories&filter[2][parent]=group_root&filter[2][operator]=OR&filter[3][parent]=group_categories&filter[3][path]=category&filter[3][operator]==&filter[3][value]=faq&filter[4][parent]=group_categories&filter[4][path]=category&filter[4][operator]==&filter[4][value]=manual

Facets

With facets, you can return aggregations alongside the search results. This is useful for filters in a search interface, such as counts per category, author, or source.

Each facet rule supports:

  • path: the field to group by

  • limit: maximum number of buckets

  • min_count: minimum number of results per bucket

  • operator: AND or OR

  • exclude_tags: optional, to exclude filters with the same tags during facet calculation

Example:

GET https://{klant}.vragen.ai/api/v1/documents/search?query=parking&facets[0][path]=category&facets[0][limit]=5&facets[0][min_count]=1&facets[1][path]=source&facets[1][limit]=10
GET https://{klant}.vragen.ai/api/v1/documents/search?query=parking&facets[0][path]=category&facets[0][limit]=5&facets[0][min_count]=1&facets[1][path]=source&facets[1][limit]=10
GET https://{klant}.vragen.ai/api/v1/documents/search?query=parking&facets[0][path]=category&facets[0][limit]=5&facets[0][min_count]=1&facets[1][path]=source&facets[1][limit]=10

In the response, facet results are included under meta.facets.

Example request

The example below searches semantically in documents, limits the results to source website, requests facets for category, and sorts descending by date.

GET https://{klant}.vragen.ai/api/v1/documents/search?query=sustainability&maxDistance=0.5&filter[0][path]=source&filter[0][operator]==&filter[0][value]=website&facets[0][path]=category&facets[0][limit]=10&sort=-date&page[offset]=0&page[limit]=10
GET https://{klant}.vragen.ai/api/v1/documents/search?query=sustainability&maxDistance=0.5&filter[0][path]=source&filter[0][operator]==&filter[0][value]=website&facets[0][path]=category&facets[0][limit]=10&sort=-date&page[offset]=0&page[limit]=10
GET https://{klant}.vragen.ai/api/v1/documents/search?query=sustainability&maxDistance=0.5&filter[0][path]=source&filter[0][operator]==&filter[0][value]=website&facets[0][path]=category&facets[0][limit]=10&sort=-date&page[offset]=0&page[limit]=10

Example response

The search endpoints return results as a JSON:API collection with resource type semantic-searchables.

{
  "meta": {
    "total": 2,
    "limit": 10,
    "offset": 0,
    "facets": {
      "category": [
        {
          "filter": "manual",
          "count": 8
        },
        {
          "filter": "faq",
          "count": 3
        }
      ]
    }
  },
  "jsonapi": {
    "version": "1.0"
  },
  "links": {
    "self": "https://{klant}.vragen.ai/api/v1/documents/search"
  },
  "data": [
    {
      "type": "semantic-searchables",
      "id": "9001",
      "attributes": {
        "url": "https://www.domein-met-het-nieuwe-zoeken.nl/duurzaamheid",
        "favicon": "https://www.domein-met-het-nieuwe-zoeken.nl/favicon.ico",
        "summary": "Summary or relevant content of the found result.",
        "title": "Sustainability",
        "external_reference": "scrapedPage:9001",
        "last_updated": "2026-05-15T12:00:00+00:00",
        "relevance_score": 0.92,
        "distance": 0.08,
        "knowledge_scopes": {
          "topic": "sustainability"
        },
        "metadata_fields": {
          "category": "manual",
          "author": "Example Municipality"
        },
        "mime_type": "text/html"
      }
    }
  ]
}
{
  "meta": {
    "total": 2,
    "limit": 10,
    "offset": 0,
    "facets": {
      "category": [
        {
          "filter": "manual",
          "count": 8
        },
        {
          "filter": "faq",
          "count": 3
        }
      ]
    }
  },
  "jsonapi": {
    "version": "1.0"
  },
  "links": {
    "self": "https://{klant}.vragen.ai/api/v1/documents/search"
  },
  "data": [
    {
      "type": "semantic-searchables",
      "id": "9001",
      "attributes": {
        "url": "https://www.domein-met-het-nieuwe-zoeken.nl/duurzaamheid",
        "favicon": "https://www.domein-met-het-nieuwe-zoeken.nl/favicon.ico",
        "summary": "Summary or relevant content of the found result.",
        "title": "Sustainability",
        "external_reference": "scrapedPage:9001",
        "last_updated": "2026-05-15T12:00:00+00:00",
        "relevance_score": 0.92,
        "distance": 0.08,
        "knowledge_scopes": {
          "topic": "sustainability"
        },
        "metadata_fields": {
          "category": "manual",
          "author": "Example Municipality"
        },
        "mime_type": "text/html"
      }
    }
  ]
}
{
  "meta": {
    "total": 2,
    "limit": 10,
    "offset": 0,
    "facets": {
      "category": [
        {
          "filter": "manual",
          "count": 8
        },
        {
          "filter": "faq",
          "count": 3
        }
      ]
    }
  },
  "jsonapi": {
    "version": "1.0"
  },
  "links": {
    "self": "https://{klant}.vragen.ai/api/v1/documents/search"
  },
  "data": [
    {
      "type": "semantic-searchables",
      "id": "9001",
      "attributes": {
        "url": "https://www.domein-met-het-nieuwe-zoeken.nl/duurzaamheid",
        "favicon": "https://www.domein-met-het-nieuwe-zoeken.nl/favicon.ico",
        "summary": "Summary or relevant content of the found result.",
        "title": "Sustainability",
        "external_reference": "scrapedPage:9001",
        "last_updated": "2026-05-15T12:00:00+00:00",
        "relevance_score": 0.92,
        "distance": 0.08,
        "knowledge_scopes": {
          "topic": "sustainability"
        },
        "metadata_fields": {
          "category": "manual",
          "author": "Example Municipality"
        },
        "mime_type": "text/html"
      }
    }
  ]
}

Meaning of response fields

summary

In documents/search, this field contains a summary or representative content of the document.

In document-chunks/search, this field contains the content of the specific document fragment that was found as a result.

relevance_score

A score indicating how relevant the result is to the search query.

distance

The semantic distance between the query and the result. Lower is usually better.

metadata_fields

The metadata associated with the document, where available.

knowledge_scopes

The knowledge scopes linked to the document, where available.

Practical considerations

  • Use documents/search when you want to display results at document level.

  • Use document-chunks/search when you want to display the most relevant text fragment right away.

  • Keep snake_case in mind for metadata fields in filters and facets.

  • Not every visible response field is automatically filterable or sortable.

  • Which filter, facet, and sort fields are available depends on how the knowledge base of the respective customer is set up.

Support

Based on the information and examples above, you should have no trouble setting up a connection to our API search endpoints. If you still have questions, please contact our support team at info@vragen.ai.