# Quickstart

> Create a key, run your first search, and read what comes back. A working request in under two minutes, in curl, TypeScript, and Python.

Canonical page: https://www.refolk.ai/developers/quickstart



Create a key, send one request, read the shortlist. Everything below runs
against your real account and your real credits, so the first search you make
from your terminal is the same search the app makes.

- [Run one now, no code](https://www.refolk.ai/developers/playground): The playground executes any endpoint on your session, prefilled.
- [Put it in an assistant](https://www.refolk.ai/developers/mcp): Claude, Cursor, VS Code, and anything else that speaks MCP.

## Create a key

1. **Open the API page** - [/hire/api](/hire/api) has the key panel, the reference, and a link to the playground.
2. **Name it** - Call it after the thing that will use it, so a list of keys reads like a list of jobs.
3. **Press create** - Copy the key there and then. It is shown once and never again.

Keys start with `rfk_live_`. Only the hash is stored, so there is no way to
show one again, including to me: a lost key is revoked and replaced. An account
can hold 10 at once.

> **Treat it like a password**
>
> A key spends your credits, and anyone holding it can run any search your
> account can. Keep it in an environment variable, never in a repository, and
> revoke it the moment you think it has leaked.

## Your first call

The cheapest way to check a key is wired up correctly. It costs nothing and
tells you which key you are holding.

**curl**

```bash
export REFOLK_API_KEY="rfk_live_..."

curl https://www.refolk.ai/api/v1/me \
  -H "Authorization: Bearer $REFOLK_API_KEY"
```

**TypeScript**

```typescript
const res = await fetch("https://www.refolk.ai/api/v1/me", {
  headers: { Authorization: `Bearer ${process.env.REFOLK_API_KEY}` },
});
console.log(await res.json());
```

**Python**

```python
import os, requests

res = requests.get(
    "https://www.refolk.ai/api/v1/me",
    headers={"Authorization": f"Bearer {os.environ['REFOLK_API_KEY']}"},
)
print(res.json())
```

A key that is missing, mistyped, or revoked comes back as a `401` with a
sentence saying which. Anything else and you are ready to search.

## Search in plain English

One sentence in, a ranked shortlist out. This is the same run the app makes
when you type into the search box, and it takes about as long: thirty to ninety
seconds, because it is reading sources live rather than querying a table.

### `POST /api/v1/search`

Describe who you are looking for and get back a ranked shortlist with the evidence behind each pick.

**Cost:** ~10 reserved, reconciled down

**curl**

```bash
curl https://www.refolk.ai/api/v1/search \
  -H "Authorization: Bearer $REFOLK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "Staff backend engineers in NYC who shipped Rust in production"}'
```

**TypeScript**

```typescript
const res = await fetch("https://www.refolk.ai/api/v1/search", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.REFOLK_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    query: "Staff backend engineers in NYC who shipped Rust in production",
  }),
});

if (!res.ok) {
  const { error } = await res.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { people, credits } = await res.json();
console.log(`${people.length} people, ${credits.charged} credits`);
```

**Python**

```python
import os, requests

res = requests.post(
    "https://www.refolk.ai/api/v1/search",
    headers={"Authorization": f"Bearer {os.environ['REFOLK_API_KEY']}"},
    json={"query": "Staff backend engineers in NYC who shipped Rust in production"},
    timeout=180,
)
res.raise_for_status()

for p in res.json()["people"]:
    print(p["name"], "-", p.get("reason", ""))
```

Run this request in the playground: https://www.refolk.ai/developers/playground?endpoint=search. Runs on your account. Reserves 10 credits and refunds what it does not use.

```json
{"query": "Staff backend engineers in NYC who shipped Rust in production"}
```

What comes back:

```json
{
  "answer": "I found 24 staff-level backend engineers in NYC with Rust shipped in production.",
  "people": [
    {
      "key": "gh-someone",
      "name": "A Person",
      "currentTitle": "Staff Software Engineer",
      "currentCompany": "Some Company",
      "location": "New York, NY",
      "reason": "Ships Rust in production; maintains a widely used async crate.",
      "signals": ["4 years of Rust commits", "Staff title since 2023"],
      "githubUrl": "https://github.com/someone",
      "linkedinUrl": "https://www.linkedin.com/in/someone"
    }
  ],
  "companies": [],
  "repos": [],
  "credits": { "charged": 6, "balance": 494 }
}
```

> **Set a generous timeout**
>
> A search that reads live sources takes as long as the sources do. The default
> timeout in most HTTP libraries is far shorter than that, so set yours to three
> minutes or more, and do not put this endpoint on a request path somebody is
> waiting on synchronously.

## Which of the two searches you want

- **[Search in plain English](/developers/agentic-search)** when the ask needs
  judgement. It plans the search, reads sources live, cross-references them,
  and attaches the evidence for every pick. Slower, costs more, and it will
  find people a filter cannot describe.
- **[Search with filters](/developers/structured-search)** when you already
  know the criteria. Nothing is ranked and no model runs, so the same filters
  return the same page tomorrow. 1 credit, a second or
  two, and it paginates.

A common pattern uses both: write the brief once in English, keep the filter
set it produces, and run the structured search on a schedule from then on.
That is what [the translate endpoint](/developers/structured-search#turning-a-sentence-into-a-filter-set)
is for.

## Where to go next

- [Credits and limits](https://www.refolk.ai/developers/credits-and-limits): What each call costs and how fast you may call it.
- [Errors](https://www.refolk.ai/developers/errors): One error shape, and which failures are worth retrying.
- [MCP server](https://www.refolk.ai/developers/mcp): Give an assistant the same two searches.
- [OpenAPI document](https://www.refolk.ai/api/v1/openapi.json): Generate a client instead of writing one.



---

## More of the API documentation

- [Authentication](https://www.refolk.ai/developers/authentication.md): How API keys work: creating one, sending it, rotating it, and what happens when one leaks. Keys are shown once and hashed at rest.
- [Credits and limits](https://www.refolk.ai/developers/credits-and-limits.md): What each call costs, how a search is reserved and reconciled, what the rate limits are, and how to check a balance before a long run.
- [Playground](https://www.refolk.ai/developers/playground.md): Run any endpoint from the browser, signed in, on your own credits. Prefilled examples, the real response, and the equivalent curl for your own code.
- [Search in plain English](https://www.refolk.ai/developers/agentic-search.md): POST /v1/search. One sentence in, a ranked shortlist out, with the evidence behind every pick. Blocking or streamed as server-sent events.
- [Search with filters](https://www.refolk.ai/developers/structured-search.md): 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.
- [Errors](https://www.refolk.ai/developers/errors.md): One error shape for every endpoint, a closed set of types, and which of them are worth retrying. What gets refunded when a call fails.
- [MCP server](https://www.refolk.ai/developers/mcp.md): Give Claude, Cursor, VS Code, or any MCP client the ability to search for people mid-conversation. One URL, one header, four tools.
- [OpenAPI document](https://www.refolk.ai/api/v1/openapi.json): the machine-readable specification.

Authenticate with `Authorization: Bearer rfk_live_...`. Keys are created at https://www.refolk.ai/hire/api.