Skip to main content
Inputs: what (free text — a product, technology, or capability) · optional location. Returns: the companies whose business is that thing. This is the template for the long tail: corrugated cardboard, solid-state batteries, hydrogen electrolyzers, quantum computing. GOI’s corpus is SME- and niche-heavy and web-verified, so the companies exist — the trick is precision. A bare semantic search drifts to adjacent topics; the fix is to anchor.

The recipe

Set ISTARI_API_KEY, then swap in your what and anchor terms. The request maps to POST /v2/search.
import os
import requests

API_KEY = os.environ["ISTARI_API_KEY"]


def find_niche_companies(what: str, anchor: str) -> list[dict]:
    body = {
        "describe": what,  # rich description — carries the specifics
        "keywords": {
            "must_all": [anchor],  # the one word that MUST be in the description
            "must_not": ["consulting", "recruitment", "marketing agency"],
        },
        "filters": {
            "nace_code": ["NACE C: Manufacturing"],  # optional — drop to include services
        },
        "columns": ["domain", "name", "country", "nace_code"],
        "size": 15,
        "dedup": True,
    }
    resp = requests.post(
        "https://api.istari.ai/v2/search",
        headers={"x-api-key": API_KEY, "Content-Type": "application/json"},
        json=body,
    )
    return resp.json()["data"]


for row in find_niche_companies("quantum computing", "quantum"):
    print(row["domain"], "-", row["name"])
The anchor (keywords.must_all) is what turns a fuzzy semantic match into a precise one. The describe field carries the nuance the anchor can’t (solid-state, green hydrogen, fault-tolerant).

What each lever does

LeverRole
describeFull natural-language description. Carries specificity the single anchor word can’t.
keywords.must_allThe anchor. The defining term that must appear in the company’s description. This is what removes drift.
keywords.must_anyUse instead of must_all for spelling/synonym variants (electrolyzer/electrolyser, e-bike/electric bike).
keywords.must_notStrips perennial noise — consultancies, recruiters, agencies. Add "distributor","reseller" to keep only makers.
filters.nace_code = COptional. Restricts to manufacturers when you want builders, not services.

Validated examples

One pattern, five wildly different niches — all returned the real players:
Niche (what)AnchorRepresentative hits
Quantum computingquantumRigetti, PsiQuantum, Quantum Circuits, Anyon, SEMIQON
Solid-state batteriesbatterySolid Power, QuantumScape, QingTao, Jinyu
Vertical farmingvertical farmingNetled, GoodLeaf, 4D Bios, AGEYE
Hydrogen electrolyzerselectrolyzer/electrolyser (must_any)Exion Hydrogen, CENmat, PERIC, Electrogenos
Corrugated cardboardcorrugated, cardboardKartonex, Bipack, EICSA, SouthEastern

Notes

  • The anchor is everything. Drop keywords.must_all and the semantic query drifts to neighbors (battery analytics, packaging consultants). Keep it tight and literal.
  • Handle spelling/synonyms with must_any. ["electrolyzer","electrolyser","electrolysis"] caught makers using any spelling. Same for regional terms.
  • One anchor word beats two. ["corrugated"] pulled some corrugated-metal makers; ["corrugated","cardboard"] (both required) fixes it. Add a second anchor only to disambiguate.
  • Ignore the Total field in keyword mode — it shows 0 while returning a full page. Count the rows.
  • Don’t set min_score — hybrid retrieval collapses under a floor here.
  • This is also how you find “innovative / deep-tech companies in X”: anchor on the technology, not on a company type (startup typing is sparse in the corpus and will cost you real matches).