Global Endpoint
Besides the column filter, the bundle exposes a standalone endpoint that runs a kNN search directly, without going through a grid request body. This is what quick search's All tab uses to return assets and data objects in one merged ranking.
GET /pimcore-studio/api/bundle/backend-power-tools/semantic-search/search
curl -G 'https://<host>/pimcore-studio/api/bundle/backend-power-tools/semantic-search/search' \
--data-urlencode 'query=red sports car' \
--data-urlencode 'target=image' \
--data-urlencode 'page=1' \
--data-urlencode 'pageSize=50' \
-H 'Authorization: Bearer <token>'
Request contract
| Parameter | Default | Meaning |
|---|---|---|
query | (required) | 1–1000 characters. Trimmed, then truncated to 1000 characters before embedding; empty after trimming is rejected. |
target | text | "image" or "text". Any other value is rejected. |
page | 1 | |
pageSize | 50 |
Unlike the column filter, this endpoint has no per-element-type default for target — the filter defaults
assets to "image", the endpoint defaults to "text" when the parameter is left out.
Target semantics and coverage
target=imageembeds the query against theimage_searchusage and returns assets only.target=textembeds the query against thesemantic_text_searchusage and returns assets and embedding-enabled data object classes together. Both element types share the same usage and vector space for text, so one query embedding produces a single comparable ranking across them — there is no per-type scoring pass to reconcile.
Candidate pool
Each request runs a single kNN clause with k = semantic_search.global_search_candidate_cap (default
150), applied per index. The element-search alias spans every embedding-bearing index, so the
effective candidate pool before pagination is k × <number of embedding-bearing indices>, not a global
top-k. The endpoint has no listing filters (only workspace permissions), so every candidate is searched
for in every index: keep this cap small. The listing candidate_cap does not apply here. See
Semantic search settings.
The default minimum score of the target (semantic_search.targets.<target>.default_min_score, else the
built-in default) cuts off weak candidates, like in the grid, see
Threshold contract. For target=text, assets and data objects
share one usage and model, so one threshold applies to both. The endpoint has no per-request minScore.
Status codes
| Code | Cause |
|---|---|
400 | SemanticSearchUnavailableException: the inference service could not embed the query (outage, timeout, provider error). The message is the translated bpt_semantic_search_unavailable. |
403 | The caller lacks bptb_semantic_search_permission. |
404 | Embeddings are disabled, or the search engine does not support query-clause kNN. |
422 | query is missing or empty after trimming, or target is not image/text. |
It hard-fails, it does not degrade
Like the column filter (including its exports and
batch actions), this endpoint hard-fails with 400 when the query cannot be embedded, with the same
translated, user-facing message and no technical details. Neither falls back to plain results: an outage
is surfaced to the caller rather than swallowed.
Availability data
GET /pimcore-studio/api/settings contributes a backend_power_tools_semantic_search block, so the
Studio UI only offers a smart search mode where embeddings can actually answer it. The key is absent
entirely when embeddings are disabled or the engine does not support query-clause kNN — its presence is
the feature flag.
"backend_power_tools_semantic_search": {
"candidate_cap": 10000,
"targets": {
"image": {
"enabled": true,
"default_min_score": 8,
"element_types": ["asset"],
"asset_types": ["image"]
},
"text": {
"enabled": true,
"default_min_score": 20,
"element_types": ["asset", "object"],
"asset_types": ["image", "document", "text"],
"object_classes": ["Car", "Customer"]
}
}
}
| Key | Meaning |
|---|---|
candidate_cap | The configured semantic_search.candidate_cap; the UI shows it in the score filter hint as the result-set limit. |
targets.<image|text>.default_min_score | The resolved default threshold (percent) for that target: the configured semantic_search.targets.<target>.default_min_score, else the built-in default. The UI shows it as the placeholder of the score filter input. An untouched filter sends no minScore, and the backend applies this default. |
targets.image.enabled | Requires image in the asset scope and a mapped image_search usage. |
targets.text.enabled | Requires a mapped semantic_text_search usage and at least one text-bearing surface: a non-empty object class allowlist, or at least one asset type in scope. |
element_types | Built from the surfaces that are actually on: "asset" when the asset scope is non-empty, "object" when the class allowlist is non-empty. |
asset_types | The configured asset types; present only when "asset" is in element_types. |
object_classes | The configured class allowlist, regardless of whether "object" is currently in element_types. |
This is what fills the coverage hints and warnings in the mode dropdown, see Search Modes.