On this page

Golden searches within one entity, and offers two ways in:

OperationFor
POST /api/golden/{entity}/searchA structured query: a record fragment whose fields belong to the entity dataset
POST /api/golden/{entity}/search/textA free-text query: one line, the way a search bar works

Record search allows VIEWER, STEWARD, and ADMIN, within their data grants.

Examples use the Aurelia Utilities sample, whose entity is sample-customer-entity.

Discover searchable fields

Do this before hard-coding field names. The answer is generated from the entity’s indexer, and it is the same answer the web application uses to build its search bar.

curl --fail-with-body --silent --show-error \
  --header "Authorization: Bearer ${GOLDEN_TOKEN}" \
  "${GOLDEN_URL}/api/golden/sample-customer-entity/search/capabilities"
{
  "entity": "sample-customer-entity",
  "searchable": true,
  "freeTextIndexed": true,
  "fields": [
    { "mapping": "by-tax-id", "columns": ["taxId"], "matching": "EXACT", "combined": false, "freeText": true },
    { "mapping": "by-email", "columns": ["email"], "matching": "EXACT", "combined": false, "freeText": true },
    { "mapping": "by-phone", "columns": ["phone"], "matching": "EXACT", "combined": false, "freeText": true },
    { "mapping": "by-name-postcode", "columns": ["fullName", "postcode"], "matching": "FUZZY", "combined": true, "freeText": true }
  ]
}

combined: true means the mapping’s columns form one key together — searching fullName alone does not use by-name-postcode. Use this response to adapt search controls to the entity’s current mappings.

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "Authorization: Bearer ${GOLDEN_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{
    "record": { "taxId": "12345678Z" },
    "options": {},
    "pageNumber": 0,
    "pageSize": 10
  }' \
  "${GOLDEN_URL}/api/golden/sample-customer-entity/search"

record is required and cannot be empty. Search behavior follows the entity’s indexer, including which fields bring candidates together and how text is normalized.

The request can also carry:

FieldDefaultPurpose
transformationNoneApply a named transformation to the submitted record before searching
entityfalseInclude entity information in the response
filterNoneA metadata filter, the same one the record page sends, applied to the records reached
tableTypeBothTABLE searches only current records; HISTORY only historical ones
pageSize10At most 1000. A larger value is a 400, not a silent truncation
optionsDefaultsSee below

Search options

OptionDefaultEffect
identitytrueSearch by identity when the submitted record carries one
provenancetrueLook up a free-text term as a source record identifier (_source._src_id)
exactEXACTExact-match type: EXACT, PREFIX, SUFFIX, or INFIX
combineANYHow several filled fields combine: ANY or ALL
fieldModesPer mappingPer-column probe mode: MAPPING, EXACT, or SIMILAR
fuzzytrueAlso consider fuzzy matches
fuzzyMaximumTypos2Maximum typographical errors for fuzzy search
geotrueAlso consider geographic matches
geoPrecisionDefaultGeographic area precision, L1–L10
geoSteps1Neighboring geographic steps
radiusMeters0Radius for a geographic search. Zero or negative falls back to geoPrecision
maximumResults-1Result cap; -1 means no count limit
maximumDuration5 secondsSearch processing time limit

combine defaults to ANY in the API. The advanced web form sends ALL. With ANY, adding another field can broaden the results; with ALL, every filled field must match. Set this option explicitly.

fieldModes is the API form of the advanced form’s per-field Exact / Similar switch. A column absent from the map is probed with its mapping’s own matching type. It is meaningful only for structured search: free text always probes by word similarity.

The five-second default duration means a broad search is time-bounded. Choose a duration appropriate to the workflow rather than assuming every search is exhaustive.

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "Authorization: Bearer ${GOLDEN_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{"query":"Ana Garcia Munoz","pageNumber":0,"pageSize":10}' \
  "${GOLDEN_URL}/api/golden/sample-customer-entity/search/text"

The field is query, not text. Sending text answers “Invalid null or empty search query”.

Whitespace separates terms and double quotes hold a phrase together. Every term is probed against every searchable field, the record identifier, and source identifiers when provenanceSearchable is true, and a record matching more terms ranks higher.

Two behaviors have no equivalent in structured search:

  • History is included in the same result, with a merged record resolved forward to the record that survived it.
  • similarity bounds the word-similarity threshold. It must be below 1.0; a value at or above it is a 400, because word similarity can only reach 1.0 on a whole-key match.

The query above returns three records from the sample:

SourceReferenceFull nameTax IDEmail
CRMCRM-DUP-0001ANA Garcaí Muñoz12345678ZAna.Garcia@Example.com
BILLINGBILL-0001Ana Garcia Munoz(empty)ana.garcia@
CRMCRM-0001Ana García Muñoz12345678Zana.garcia@example.com

A structured search on taxId returns only two: the billing record has no tax identifier. Free-text search can find this record through its name even though that identifier is absent.

Read the response

FieldMeaning
searchThe record criteria Golden used, after any requested transformation
resultRecords on the current page
countTotal matching record count
truncatedThe search stopped at its limit. The result is part of the answer
pageCurrent pagination information
entityOptional entity information when requested

Page until the page information shows no remaining results. Check truncated: a narrower or longer term is what fixes it, not another page.

Results can carry _search metadata describing why a record was returned:

FieldMeaning
indexIndexer mapping that found the result
matchMatched text, normalized
typeID, SOURCE, EXACT, PREFIX, SUFFIX, INFIX, FUZZY, FUZZY_LSH, GEOGRAPHIC, or NONE
rankRelative match-strength signal
exactWhether the match was exact
originHow the record was reached, which is not the same question as what matched it

Search result origin

ValueMeaning
DIRECTThe record’s own value for that mapping is what matched
CLUSTERThe record came in through a bucket connected to the one that matched. Its own value may be nothing like the search term
HISTORYThe record lives in the history relation. It is not current
MERGED_FORWARDThe record is current and was reached through a record merged into it. The matching value belonged to the absorbed record and is in none of this record’s columns. sourceId names the record it came through

For CLUSTER and MERGED_FORWARD, explain that the result was reached through another record rather than through a direct match on its own values. A MERGED_FORWARD result is the current surviving record, not a history row.

Use the evidence to understand the lookup; do not reproduce ranking behavior from rank, and do not use it for identity decisions. That is what the classifier and the duplicate review are for. See the record metadata reference.

If search returns nothing

Check that:

  • the entity identifier and field names are correct — search/capabilities settles both;
  • the entity is enabled and its synchronization has completed;
  • the relevant indexer mapping participates in search;
  • combine is the combination you meant;
  • normalization and matching options suit the submitted value; and
  • the caller is using the intended environment and credential.

An empty result means this search found no matching record under these options. If the question is whether a raw row exists, inspect the entity’s table separately with Query table data.

Golden 3.0.0 · Published 2026-10-04