Find

Find companies or people not yet in your workspace

Required permissions: body.target equals people: people:read; body.target equals companies: accounts:read. Other or missing values: no additional scopes; request validation still applies.

Search for companies and people you do not already have. It never writes: you get candidates, and you import the ones you want.

For explicit criteria, use mode: direct with filters. Reads stored company and people records with no sentence interpretation or external search. query is rejected. Each call returns one page of at most 100 records; follow nextCursor to continue. Company records without websites are kept and can be read again by filters.companyIds. A direct companies search can combine company criteria with filters.title to return companies with a matching current employee, once per company. People results include their matching current company. A company reaching perCompany sets truncated: true with a note because additional matching people may exist. Omitting mode preserves the usual search behavior below.

Say what you want in one of two ways, or both.

  • query — a sentence. Trayo interprets it and ranks results by relevance. interpreted in the response tells you what it read out of the sentence, in the same filters shape you can send back. One ranked page of at most 50; no cursor.
  • filters — exact attributes: industry, headcount, headquarters, funding stage, founded year, technologies, legal form, and for people a title. Applied exactly as sent, never interpreted, never fail-open: a company with no value for a filtered attribute is excluded. Paginated. A companies search without a title can use only country, founded year, technology or company type: it checks a bounded set of the largest companies and reports led_by_headcount, so its matches are not exhaustive. A people search or a company search with a title needs named companies or industries, hq.cities, hq.states, fundingStages or a headcount band. A funding stage selects a set on its own. Read GET /v1/find/industries before your first industry filter, because the values are a closed taxonomy.
  • both — the sentence ranks, the filters decide. Rows Trayo cannot check are dropped.

target: people returns people with their current company. "founders at seed-stage software companies" is {"target": "people", "filters": {"industries": ["software development"], "fundingStages": ["seed"], "title": {"any": ["founder"]}}}. Company filters describe the employer; title describes the person. With a query, a people search takes title only.

Searching inside companies you already know. Name them instead of describing them: filters.companyWebsites takes their websites (["stripe.com", "https://www.acme.example"]), the form you already have without asking this API for anything. It replaces every other company filter, and takes no query beside it. (filters.companyIds, which takes an id a previous search returned, is the older form of the same thing and replaces it in turn; websites are what to reach for.) Each website resolves to at most one company, and resolvedWebsites in the response says which: several company profiles can share a domain, so a website resolves only to a profile whose name matches the domain; check it before trusting the page. A website that does not resolve is left out of the search and listed in unresolvedWebsites, never dropped without saying so: the page covers only the websites in resolvedWebsites. reason: "not_found" means no company on that domain: fix the spelling, send the company's own domain, or describe that company with filters in a separate search. reason: "uncertain" means the domain carries several possible companies and none clearly owns it; its alternatives list them (id, name, headcount). Show them to the user, or search again with filters.companyIds set to the right alternative's id. When no website resolves at all, the answer is a 404 company_not_found naming them.

Reading the response. data holds one row shape per target. hasMore/nextCursor page a filters-only search. truncated means more matched than this search can show — narrow, do not page deeper. known: false on a company means the sentence search found something Trayo does not hold. state: alreadyAdded means it is in your workspace; for "find N new companies", send filters.excludeWorkspace: true and those rows are left out, so the page fills with companies you do not have.

Before re-running a thin search, read interpreted, truncated and degraded. They say whether your criteria were enforced, whether the set is larger than reachable, and whether the search was incomplete — and a search that ran counts against the quota whether or not it was useful. Outside direct mode, every company row carries a url: rows with no website are dropped before the page is filled and counted in droppedUnaddressable, because POST /v1/accounts could not import them.

Importing. Companies: POST /v1/accounts/batch with {name, url} from each row (url is ready to send). People: POST /v1/people/batch with {fullName, title, linkedinUrl}; the company links by website when known. Contact details are a separate step: POST /v1/contacts/lookup with the linkedinUrl.

target: companies needs the accounts:read scope, target: people needs people:read. A search with a query draws on the workspace's search quota when it runs; a filters-only search does not.

post/v1/find

Request

  • Base URL: https://api.trayo.ai
  • URL: https://api.trayo.ai/v1/find
  • Auth: HTTP bearer

Headers

idempotency-keystring

For searches with a query, replay the saved response without repeating the search. Reuse only with the same request body. Filters-only searches do not use this key.

Request body

target'companies' | 'people' required

What to return: companies or people. People are returned with their current company.

mode'direct'

Use direct for a bounded search of stored company and people data with exact filters. No sentence interpretation or external search. Requires filters, rejects query, and returns one page of at most 100 records. Company records without websites are kept and can be searched again by companyIds. A direct title search checks at most 30 companies per request in sort order (largest by default, smallest with smallest_first): send at most 30 companyIds or companyWebsites at a time. Omit mode to retain the usual query or filters search.

querystring

A sentence describing what to find. Trayo interprets it and ranks results by relevance; interpreted in the response says what it read. Omit it to search by filters alone, which is exact and paginated. Send both to rank by the sentence and keep only rows that pass the filters. On a people search, the company filters (companyWebsites, companyIds, industries, headcount, hq and the rest) are checked against each ranked person's current employer, which the row then carries: companyWebsites must be that employer's own website. A person whose employer fails them, or whose current employer Trayo cannot identify, is left out. The page is not refilled, and a query_page_filtered note counts who was left out. For a filters-only people search, omit query and use mode: "direct" with filters.title and named companies or an indexed company filter such as industries or headcount; country, founded-year, technology and company-type filters alone are insufficient beside a title. A title-free companies search can use those filters alone, checking a bounded set of the largest companies (led_by_headcount).

sort'largest_first' | 'smallest_first'

Filters-only. Page order by company headcount: largest_first (the default) or smallest_first. smallest_first needs filters.headcount.min of at least 1, because companies with no recorded headcount would otherwise come first. A search whose title is rare is ordered by company id instead and ignores sort; its pages carry a title_matched_first note. A search with a query is ranked by relevance and takes no sort.

perCompanyinteger

target: people, filters-only. People read per company before paging, most senior title first. Default 4, at most 25. Keeps one large employer from filling every page.

limitinteger

Page size. Default 25, at most 100. A search with a query returns at most 50.

cursorstring

The nextCursor from the previous page, sent back verbatim WITH THE SAME REQUEST. Filters-only searches page; a search with a query returns one ranked page and rejects a cursor.

Example request

{
  "target": "people",
  "filters": {
    "industries": [
      "software development"
    ],
    "hq": {
      "regions": [
        "europe"
      ]
    },
    "headcount": {
      "min": 10,
      "max": 200
    },
    "fundingStages": [
      "seed",
      "series_a"
    ],
    "foundedYear": {
      "min": 2019
    },
    "title": {
      "any": [
        "founder",
        "cto"
      ],
      "exclude": [
        "assistant"
      ]
    }
  },
  "perCompany": 2,
  "limit": 25
}

Response

The search ran. An empty data array is a successful search that matched nothing — check truncated, degraded and interpreted before retrying.

target'companies' | 'people' required
hasMoreboolean required

A next page exists. People pages fill company by company, so a page can end before every matched company has been reached — keep paging until false. Always false on a sentence search, which returns one ranked page.

nextCursorstring nullable required
truncatedboolean required

The result is or may be incomplete. On a sentence search: more candidates than the page. On a filters-only search: the scan reached its cap, possibly even on a full page, so the pages you can reach are only the companies reached within the cap, not all of the set — notes says when that cap was the per-value budget of a multi-value filter, and which values ran out. Either way the answer is to narrow, not to page deeper. In direct people searches, also true when an employer reached perCompany; additional matches may exist there, and raising perCompany can reveal them. Also true when the page was checked against a sample of the title's roles (title_matches_sampled).

degradedboolean required

Part of this sentence search did not answer, so a thin result may not mean a genuine absence of matches. Always false on a filters-only search.

droppedUnaddressableinteger required

Company rows this search found and then dropped for carrying neither a website nor a url. POST /v1/accounts would accept such a row — url is optional there — but deduplication keys on the website, and a sentence match with no website at all is overwhelmingly a directory, a job board or an institution rather than a company. They are dropped on that quality ground, so every row left in data can be acted on. On a search with a query they are dropped BEFORE the page is filled, so the page still reaches its size; on a filters-only search the page has already been read at its size, so a dropped row shortens it and hasMore is unaffected. A high number against a thin data means the sentence matched directories, job boards and institutions rather than companies — name the kind of company you want. Always 0 for target: people, whose rows are addressed by linkedinUrl, and in mode: direct, which keeps company records without websites and identifies them by id.

Changes

No recorded changes to this operation across all 1 revision of this API.