Skip to content
Main site Contact

Search

This page covers the public search workflow:

  • GET /api/Search
  • PUT /api/Search
  • GET /api/Image
  • PUT /api/SearchFeedback

filterStr is not a normal field. It is its own mini query string, sent as the value of a query parameter. That means:

  1. Build the inner filter string first, for example fileUID=<guid> or FT=pump housing.
  2. URL-encode the entire inner string before appending it as filterStr=....
  3. If the FT= value itself contains = or &, encode the FT value first, then encode the whole filterStr.
  • Decoded inner filter string: FT=pump housing
  • Encoded filterStr: FT%3Dpump%20housing

If the logical search text is document_type=Assembly&material=Stainless Steel:

  1. Encode the FT value: document_type%3DAssembly%26material%3DStainless%20Steel
  2. Build the decoded filterStr: FT=document_type%3DAssembly%26material%3DStainless%20Steel
  3. Encode the whole filterStr: FT%3Ddocument_type%253DAssembly%2526material%253DStainless%2520Steel

Example: repeated FT= filters for metadata-style narrowing

Section titled “Example: repeated FT= filters for metadata-style narrowing”
  • Decoded inner filter string: FT=document_type=[Assembly]&FT=material=[Stainless Steel]&FT=region=[North America]
  • Encoded filterStr: FT%3Ddocument_type%3D%5BAssembly%5D%26FT%3Dmaterial%3D%5BStainless%20Steel%5D%26FT%3Dregion%3D%5BNorth%20America%5D

The current search parser treats the following forms differently:

  • Regular metadata search: FT=document_number=AX-1000
  • Exact attribute match: FT=document_number=[AX-1000]
  • Wildcard attribute search: FT=document_number=AX-*

Use this when the search input already exists in VizSeek, or when you want a pure text/attribute search.

ItemValue
MethodGET
Path/api/Search
AuthUser bearer token
ResponseSearchResultSummary JSON
ParameterRequiredFormatNotes
filterStrYesURL-encoded nested query stringSee the encoding rules above. Omitting filterStr does not return 400 — the search simply has no input. Supply at least one of fileUID or FT inside it for meaningful results.
includeShapeletsNotrue or falseAdds shapelet detail for applicable results.
customAPINoIntegerDeprecated legacy switch. Do not use for new integrations.
searchAssemblyComponentsNotrue or falseFor assembly input, return component-level matches instead of only whole-assembly matches.
accountNameNoStringOnly use if VizSeek explicitly tells you to use it.
rankAttributeNoString (attribute field name)De-duplicate results by this attribute — at most one result per unique value, e.g. category. See De-duplicating results by an attribute.
Key inside filterStrMeaning
fileUIDSearch by an existing uploaded file UID.
FTFree-text or attribute-text search term. Repeat FT= when you want multiple text or metadata refinements.
resultFileTypeRestrict results to Image, ThreeD, TwoD, or Text.
vVolume tolerance for 3D-to-3D matching.
bbvBounding-box volume tolerance for 3D-to-3D matching.
saSurface-area tolerance for 3D-to-3D matching.
rankAttributeDe-duplicate results by this attribute — at most one result per unique value, e.g. category. See De-duplicating results by an attribute.

Additional public refinement keys may appear in SearchFilters[].QueryString in the response. When you want to refine a search, prefer reusing the QueryString values the API returns instead of inventing your own filter names.

For v, bbv, and sa, the current public format is a decimal percentage string:

  • .1 means +/-10%
  • +.2 means +20%
  • -.5 means -50%
  • +0.3/-0.4 means +30% and -40%

Python example: search by existing file UID

Section titled “Python example: search by existing file UID”
import urllib.parse
import requests
server = "https://your-server.example.com"
token = "USER_BEARER_TOKEN"
file_uid = "11c20df1-8d84-418d-93ae-db3abb5d4d14"
filter_str = urllib.parse.quote(f"fileUID={file_uid}", safe="")
resp = requests.get(
f"{server}/api/Search?filterStr={filter_str}",
headers={"Authorization": f"Bearer {token}"},
)
resp.raise_for_status()
print(resp.json())
import urllib.parse
import requests
server = "https://your-server.example.com"
token = "USER_BEARER_TOKEN"
inner_ft = urllib.parse.quote("document_number=[AX-1000]", safe="")
filter_str = urllib.parse.quote(f"FT={inner_ft}", safe="")
resp = requests.get(
f"{server}/api/Search?filterStr={filter_str}",
headers={"Authorization": f"Bearer {token}"},
)
resp.raise_for_status()
print(resp.json())
GET /api/Search?filterStr=FT%3Dpump%20housing HTTP/1.1
Host: your-server.example.com
Authorization: Bearer USER_BEARER_TOKEN

Use this when you want to upload one or more temporary search-input files and search immediately.

ItemValue
MethodPUT
Path/api/Search
AuthUser bearer token
Content-Typeapplication/json
ResponseSearchResultSummary JSON
ParameterRequiredFormatNotes
fileExtensionYesURL-encoded extension such as .png or .stpInclude the leading dot.
filterStrNoURL-encoded nested query stringSame rules as GET /api/Search.
isGZipCompressedNotrue or falseLegacy. Only use if the uploaded bytes are actually gzipped.
cropX, cropY, cropW, cropHNoIntegerDeprecated crop parameters.
includeShapeletsNotrue or falseInclude shapelet detail in response.
customAPINoIntegerDeprecated.
crawl_parameterNoStringDeprecated.
accountNameNoStringOnly use if VizSeek directs you to.
targetFidsNoComma-delimited file UID listRestrict search targets to those files.
rankAttributeNoString (attribute field name)De-duplicate results by this attribute — at most one result per unique value, e.g. category. See De-duplicating results by an attribute.

The request body is a JSON string whose contents are a JSON array of base64-encoded file byte arrays.

That means the wire body looks like this:

"[\"BASE64_FILE_1\",\"BASE64_FILE_2\"]"

Do not send a raw JSON array like ["BASE64_FILE_1"]. The controller receives a string and then deserializes that string into byte[][].

A single base64 file may also be sent as a JSON string (not wrapped in an array), and is treated as a one-file search. The array form remains recommended.

Other important limits and quirks:

  • Maximum 10 input files per request.
  • The endpoint rejects obviously invalid or very short payloads before deserialization.
  • fileExtension applies to the uploaded files in this request.

Python example: visual search from one file

Section titled “Python example: visual search from one file”
import base64
import json
import requests
import urllib.parse
server = "https://your-server.example.com"
token = "USER_BEARER_TOKEN"
filename = "example-input.dxf"
with open(filename, "rb") as f:
b64_file = base64.b64encode(f.read()).decode("ascii")
body = json.dumps(json.dumps([b64_file]))
filter_str = urllib.parse.quote(
"FT=pump housing&FT=document_type=[Assembly]",
safe="",
)
resp = requests.put(
f"{server}/api/Search?fileExtension=.dxf&filterStr={filter_str}",
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
},
data=body,
)
resp.raise_for_status()
print(resp.json())

Python example: metadata narrowing with repeated FT= clauses

Section titled “Python example: metadata narrowing with repeated FT= clauses”
metadata_filter = (
"FT=document_type=[Assembly]"
"&FT=material=[Stainless Steel]"
"&FT=region=[North America]"
)
encoded_filter = urllib.parse.quote(metadata_filter, safe="")
PUT /api/Search?fileExtension=.stp&filterStr=FT%3Dpump%20housing HTTP/1.1
Host: your-server.example.com
Authorization: Bearer USER_BEARER_TOKEN
Content-Type: application/json
"[\"BASE64_FILE_1\"]"

By default a single search can return many results that share the same value of an attribute. Pass the optional rankAttribute parameter to collapse those: the search then returns at most one result per unique value of that attribute — one representative per distinct value — so the result set spans different attribute values instead of being dominated by one.

For example, with rankAttribute unset a 50-result response could be 50 files that all share the same category value; with rankAttribute=category you instead get up to 50 results, each with a different category value.

  • Pass a company attribute name — exactly as it appears in GET /api/FileAttributes. (category here is just a placeholder; use one of your own attribute names.) Matching is case-insensitive (category and Category are equivalent); the API resolves it to attributes.<name> for the backend. You may also pass the fully-qualified attributes.category.
  • Supply it either as a standalone query parameter (&rankAttribute=category) or as a key inside filterStr (alongside fileUID, FT, …). If both are present, the standalone query parameter wins.
  • It de-duplicates the result set; it does not otherwise filter results. Combine it with filterStr to narrow results as usual.
  • rankAttribute is always validated: an unknown attribute name returns 400 Bad Request with the reason. (Geometry and numeric field names are rejected the same way, via the generic not an indexed attribute for this account message.)
  • It applies to GET /api/Search and PUT /api/Search searches processed by the shape/visual backend — a file upload via PUT, or a fileUID input via GET — and is not applied to a pure free-text search (FT= with no file input) or when searchAssemblyComponents=true.
GET /api/Search?filterStr=fileUID%3D11c20df1-8d84-418d-93ae-db3abb5d4d14&rankAttribute=category HTTP/1.1
Host: your-server.example.com
Authorization: Bearer USER_BEARER_TOKEN
import urllib.parse
import requests
server = "https://your-server.example.com"
token = "USER_BEARER_TOKEN"
file_uid = "11c20df1-8d84-418d-93ae-db3abb5d4d14"
filter_str = urllib.parse.quote(f"fileUID={file_uid}", safe="")
# Replace "category" with one of your own attribute names (see GET /api/FileAttributes).
# The API resolves it to attributes.category and returns one result per unique value.
resp = requests.get(
f"{server}/api/Search?filterStr={filter_str}&rankAttribute=category",
headers={"Authorization": f"Bearer {token}"},
)
resp.raise_for_status()
print(resp.json())

Typical top-level fields:

FieldMeaning
InputFileUIDUID of the temporary input file when a file-based search was used
InputThumbnailThumbnail URL for the input file
TotalResultsNumber of returned results
ResultsListResult objects
SearchFiltersRefinement filters you can feed back into a future filterStr
SearchTimeSearch duration
MessageExtra message, often used for assembly-component cases

Typical result fields:

FieldMeaning
FileUIDResult file UID
FileNameResult file name
CompanyNameOwning company
ThumbnailURLThumbnail or shape image URL
ShapeResult.ScoreLower is better; 0.0 means exact match
ShapeResult.ViewerUrlViewer URL when available
ShapeResult.LargeFileUrlLarge image URL
ShapeResult.AttributesResult attributes shown with the match

Example response:

{
"InputFileUID": "example-uid",
"TotalResults": 2,
"ResultsList": [
{
"ShapeResult": {
"Score": 3.22989,
"Volume": 0.0,
"SurfaceArea": 0.0,
"ViewerUrl": "https://hoops.vizseek.com/view/viewer.html?...",
"DetailsUrl": "https://www.vizseek.com/ViewFile?...",
"LargeFileUrl": "https://viewfiles.vizseek.com/vizseek/.../lg.png?ver=3",
"Attributes": [
"document_type=Assembly",
"region=North America"
],
"FileHasThumbnail": true,
"FirstShapeMatchIndex": "1",
"FirstShapeMatchPageNum": "0",
"MatchPosition": "0,0,0.785398,0.472566",
"Name": "example-assembly.step"
},
"CompanyName": "Example Manufacturing",
"FileName": "example-assembly.step",
"FileUID": "00000000-0000-0000-0000-000000000000"
}
]
}

Use this to fetch the binary image or original file referenced by search results.

ItemValue
MethodGET
Path/api/Image
AuthNo bearer token. Requires the query-string token returned by search URLs.
ResponseRaw binary bytes with the file/image content type
ParameterRequiredNotes
fidYesFile UID to read from
tokenYesShort-lived image token returned by search URLs
typeNo0 = small thumbnail, 1 = large thumbnail, 2 = extracted shape, 3 = original/public file
shapeIndexNoApplies to type=0, type=1, and type=2 (selects the per-view small/large image or the extracted shape)
resp = requests.get(
f"{server}/api/Image?fid={file_uid}&type=1&token={image_token}"
)
resp.raise_for_status()
with open("result.png", "wb") as f:
f.write(resp.content)

Use this to send explicit feedback about search quality.

ItemValue
MethodPUT
Path/api/SearchFeedback
AuthUser bearer token
Content-Typeapplication/json
ResponsePlain feedback ID string
ParameterRequiredNotes
foundNotrue or false
rankNoRank of the expected result if found
expectationNoURL-encoded text, max 150 chars
helpfulnessNoInteger; the UI uses a 1-5 scale (the API does not reject out-of-range values)
userNoURL-encoded external user identifier, max 100 chars
inputFileUIDNoSearch input file UID from the search response
inputFileNameNoURL-encoded file name
otherInputNoURL-encoded extra search context
feedbackIdNoOptional GUID you want to control

The body is a JSON string containing a comma-separated result list in this format:

result_file_uid_1_score,result_file_uid_2_score

Example:

"17bc1ed1-1939-425f-bdfe-e59cbffaea16_1.05,10a5ba67-abfe-4b15-a085-e9f9a9952104_1.89"
import json
import requests
server = "https://your-server.example.com"
token = "USER_BEARER_TOKEN"
results_body = json.dumps(
"17bc1ed1-1939-425f-bdfe-e59cbffaea16_1.05,"
"10a5ba67-abfe-4b15-a085-e9f9a9952104_1.89"
)
resp = requests.put(
f"{server}/api/SearchFeedback?found=true&rank=1&helpfulness=5",
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
},
data=results_body,
)
resp.raise_for_status()
print(resp.text)