Refolk
DevelopersReference

Search with filters

View as Markdown

POST /v1/people/search. An exact filter set in, a deterministic page of people out, one credit a call. Every field, every allowed value, and how to paginate.

An exact filter set in, a page of people out. No model runs and nothing is ranked, so the same filters return the same page tomorrow, which is what makes this the one to build a pipeline on.

POST/api/v1/people/search1 credit

Deterministic, repeatable, cursor-paginated. A filter set in, a page of people out.

Body
queryobjectrequired
The filter set. Every field is optional and at least one is required.
limitintegeroptional
How many to return, 1 to 100. Defaults to 25.
cursorstringoptional
The nextCursor from a previous response.
curl https://www.refolk.ai/api/v1/people/search \
  -H "Authorization: Bearer $REFOLK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "titleIncludes": ["engineer"],
      "skills": ["Rust"],
      "countries": ["Germany"],
      "seniorityLevels": ["Senior", "Director"],
      "minYearsExperience": 6
    },
    "limit": 25
  }'

Filters are combined with AND: the query above means senior or director-level engineers, in Germany, with Rust on file, and at least six years in.

Run this in the playgroundOne credit. Returns in a second or two.
query
keywordsstringoptional
Free text, matched against the headline.
titleIncludesstring[]optional
Job titles to include, matched as substrings. "engineer" catches every kind of engineer.
titleExcludesstring[]optional
Job titles to exclude.
companyNamesstring[]optional
Employers, by their common name rather than their legal one.
companyIndustriesstring[]optional
The industry the employer is in.
seniorityLevelsstring[]optional
One or more of Owner, Founder, CXO, Partner, VP, Director, Manager, Senior, Entry. Anything else is a 400.
headcountRangesstring[]optional
Employer size, one or more of 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, 10001+.
locationsstring[]optional
Metro areas, spelled the way a profile would: "San Francisco Bay Area".
countriesstring[]optional
Country names, such as "Germany".
skillsstring[]optional
Skills listed on the profile.
minYearsExperiencenumberoptional
Lower bound on total years of experience.
maxYearsExperiencenumberoptional
Upper bound on total years of experience.
recentlyChangedJobsbooleanoptional
Only people who started somewhere new recently.
verifiedEmailOnlybooleanoptional
Only people with a verified work email on file.
currentEmployersOnlybooleanoptional
Defaults to true. Set false to match the employer filters against past roles too, which is how you find people who used to be somewhere.

An unknown value in an enum field comes back as a 400 naming the field, the value, and the list it should have come from. Nothing is charged for a request that never ran.

Pagination

Pages are walked with an opaque cursor: pass back the nextCursor you were given, change nothing else, and a null one means you have reached the end.

async function everyone(query: object) {
  const all = [];
  let cursor: string | null = null;
  do {
    const res = await fetch("https://www.refolk.ai/api/v1/people/search", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.REFOLK_API_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ query, limit: 100, cursor }),
    });
    const page = await res.json();
    all.push(...page.profiles);
    cursor = page.nextCursor;
  } while (cursor);
  return all;
}

Each page is 1 credit, so a walk over a large result set costs one credit per 100 people. Check totalCount on the first page before committing to the walk.

Turning a sentence into a filter set

Write the brief once in English, keep the filter set it produces, and run the structured search on a schedule from then on. One credit, and no search runs.

POST/api/v1/people/translate1 credit

A sentence in, the filter set the structured search takes out. Nothing is searched.

Body
promptstringrequired
Who you are looking for, in English.
currentQueryobjectoptional
An existing filter set to amend rather than replace.
curl https://www.refolk.ai/api/v1/people/translate \
  -H "Authorization: Bearer $REFOLK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "senior platform engineers at mid-size fintechs in Berlin"}'
Run this in the playgroundOne credit. No search runs.

The result is the filter set and nothing else, so you can show it to somebody, store it, diff it against the last one, or edit a field by hand before you spend anything on results.

When to reach for the other one instead

Filters cannot express "shipped Rust in production", "maintains something people depend on", or "was an engineer before founding". Those are judgements about evidence, and they are what the plain English search is for. Use filters when you know the criteria and want them applied the same way every time.

Try it on the search you came here for

Stop building boolean strings. Just describe the person.

Type one sentence. I plan the search, read GitHub, public LinkedIn and Crunchbase records, and the open web as it is right now, and hand back a ranked list with the reason next to every name.

  1. 01Describe them

    One plain sentence. Role, city, stack, stage, whatever matters to you.

  2. 02I read the web live

    GitHub, public LinkedIn and Crunchbase records, the open web. Not a database that went stale last quarter.

  3. 03You read the shortlist

    Ranked, with the reasoning under every name. Open a profile, ask a follow-up, narrow it down.

  • No boolean, no filters, no seat to buy. One box.
  • Read at search time, so a profile updated yesterday counts today.
  • Every step visible as it runs, every name with its reason.

500 free credits on sign-up. No card, no demo call. See real searches.