Instant Search
Fast typeahead lookups across agents, originators, companies, and offices — call the route directly, or mint a scoped token and query the search host yourself.
Instant Search is a fast typeahead/autocomplete lookup across agents, originators, companies, and offices. Give it a few characters of a name and it returns the top matches per entity type — built for "search-as-you-type" boxes, not for filtered analytical queries.
There are two ways to use it:
- Call the route —
POST /v1/instant-searchwith your API key. Simplest path; the API queries the search backend for you and returns grouped results. Best for server-side code. - Mint a scoped token —
GET /v1/search-tokenreturns a short-lived token plus the host to hit, so a trusted client can query the search indexes directly with per-query controls. Best for browser/client typeahead where you want sub-100ms round-trips without proxying every keystroke through your server.
For filtered, sorted, paginated searches (e.g. "all CA purchase loans over $500k"), use the entity list endpoints instead. Instant Search is for quick name lookups only.
Option 1 — Call the route
Send a POST to /v1/instant-search with your query. Authenticate exactly like any other endpoint — an x-api-key header or a Bearer token (see Authentication).
curl -X POST https://api.modelmatch.com/v1/instant-search \
-H "x-api-key: mm_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"query": "wells fargo",
"limit": 5
}'The response groups matches under results, keyed by entity type:
{
"results": {
"originators": [
{ "id": "123456", "firstName": "Jane", "lastName": "Doe", "...": "..." }
],
"companies": [
{ "id": "789012", "name": "Wells Fargo Bank, N.A.", "...": "..." }
],
"agents": [],
"offices": []
}
}Each entry carries the identifying fields for that entity (id, name, location) — enough to render a result row and then fetch the full record with the matching get* endpoint.
Request fields
| Field | Type | Default | Description |
|---|---|---|---|
query | string | — | Required. The search text (min 1 character). |
entities | string[] | all | Limit the search to specific entity types, e.g. ["originators", "companies"]. |
limit | number | 5 | Max results per entity type (1–50). |
filters | object | — | Per-entity filter strings, e.g. { "originators": "state = CA" }. |
curl -X POST https://api.modelmatch.com/v1/instant-search \
-H "x-api-key: mm_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"query": "smith",
"entities": ["originators"],
"filters": { "originators": "state = TX" },
"limit": 10
}'Option 2 — Mint your own search token
If you're powering a typeahead in the browser, proxying every keystroke through your backend adds latency. Instead, mint a scoped search token and let the client query the search host directly.
GET /v1/search-token (authenticated with your API key) returns a token, the host to query, and the indexes the token is allowed to search:
curl https://api.modelmatch.com/v1/search-token \
-H "x-api-key: mm_your_key_here"{
"token": "eyJhbGciOiJIUzI1NiJ9...",
"host": "https://search.modelmatch.com",
"indexes": ["agents", "originators", "companies", "offices"],
"expiresAt": "2026-06-25T18:40:00.000Z"
}| Field | Description |
|---|---|
token | Short-lived, scoped search token. Safe to hand to the browser. |
host | The search host to send queries to. |
indexes | The index names this token is allowed to search. |
expiresAt | ISO-8601 expiry. Mint a fresh token before this passes. |
Tokens are short-lived (minutes), by design. Always read expiresAt rather than assuming a fixed lifetime, and mint on demand — typically once per page load or session. Don't try to cache one long-term. Because the token is scoped to read-only search on these indexes, it's safe to expose to client-side code; your mm_ API key is not and must stay server-side.
Querying the host directly
The search host speaks a standard REST search API, so you query an index with POST {host}/indexes/{index}/search, passing the minted token as a Bearer credential:
curl -X POST https://search.modelmatch.com/indexes/originators/search \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
-H "Content-Type: application/json" \
-d '{
"q": "jane smith",
"limit": 5,
"attributesToSearchOn": ["firstName", "lastName"]
}'The host returns a standard result envelope:
{
"hits": [
{
"id": "123456",
"firstName": "Jane",
"lastName": "Smith",
"states": ["CA"],
"cities": ["Los Angeles"]
}
],
"query": "jane smith",
"limit": 5,
"estimatedTotalHits": 1
}attributesToSearchOn is the main reason to query directly — it restricts matching to specific fields (e.g. name-only) per request, which the route doesn't expose. Other standard search parameters (filter, offset, attributesToRetrieve, attributesToHighlight, …) work too, scoped to what the token allows.
Mint the token on your server and pass only the host + token to the browser — never the mm_ key.
Which approach should I use?
| Call the route | Mint a token | |
|---|---|---|
| Endpoint | POST /v1/instant-search | GET /v1/search-token → query host directly |
| Auth on the wire | mm_ API key | Scoped, short-lived token |
| Safe in the browser? | No — key would be exposed | Yes |
| Multi-entity in one call | Yes (grouped results) | One index per query |
| Per-field control | No | Yes (attributesToSearchOn, filters) |
| Best for | Server-side lookups, scripts | Client-side typeahead |
Errors
Both endpoints return the standard authentication errors (401, 403, 429). In addition:
| Status | Meaning |
|---|---|
400 | Validation error — e.g. an empty query. |
503 | Search backend is not configured or temporarily unavailable. |
When querying the host directly, a 401/403 usually means the token has expired — mint a fresh one from /v1/search-token and retry.
Pagination & Filtering
Narrow result sets with flat filters, boolean trees, or natural language, then iterate through them with cursor-based pagination.
Property Enrichment
Skip-trace a property to get owner contact info — names, phones, and emails. Enrich one property on demand, or queue a bulk job for up to 50,000. You're charged only for properties that return a match; cache hits and no-matches are free.