Skip to main content
FastHire

Getting Started with the FastHire API

Rakesh · September 19, 2026 · 7 min read

Before you build against this: the FastHire API is real and callable today, but it's an early version — several endpoints described on the full API Reference page aren't implemented yet, and a few behave differently than documented there. This article only describes what's actually live, verified against the current code. See "What's live vs. planned" below before you start.

Step 1: Generate an API key

  1. Go to Settings → Developer. Only an Org Admin can see this page.
  2. Select Generate API key.
  3. Give it a name (e.g. "Production integration") so you can tell your keys apart later.
  4. Choose an environment: Test or Live.
  5. Select Generate key.

Your key is shown exactly once, immediately after generation — copy it somewhere safe now. FastHire only stores a prefix (enough to identify the key in your list afterward) and a hash of the full value; if you close the dialog without copying it, there's no way to retrieve it again — you'd need to revoke it and generate a new one.

Keep it server-side. A key carries full read/write access to your org's candidate and outreach data (see the note on scoping below). Never embed one in client-side code, a mobile app, or anywhere a user of your own product could extract it — call the FastHire API from your own backend only.

Step 2: Authenticate your requests

Send the key as a bearer token on every request:

curl https://api.thefasthire.com/v1/searches \
  -H "Authorization: Bearer fh_live_yourkeyhere"

Every key belongs to one organization — you only ever see and modify that org's data. There is currently no role-based restriction on a key beyond that: a key generated by an Org Admin can read and write anything the API supports, and there's no separate, more limited key type today, despite what you may see referenced elsewhere.

What Test vs. Live actually changes

Important — this is a genuine safety gap, not a minor detail: the environment you chose when generating a key currently only changes its prefix (fh_test_... vs. fh_live_...). It does not sandbox anything. A search created with a fh_test_ key sources real candidates and spends real credits exactly like a live key. Scheduling an interview with a fh_test_ key creates a real interview, sends a real calendar invite, and sends a real confirmation email/WhatsApp message to the actual candidate — nothing is suppressed. Treat every key as live until FastHire actually builds a sandboxed test mode; don't test against real candidate data with either kind of key.

What's live vs. planned

Every endpoint below exists and works today unless marked Planned. This list is deliberately more conservative than any spec-style documentation you might see elsewhere — if it's not in this table, don't rely on it existing yet.

EndpointStatusNotes
GET /v1/searchesLiveReturns every search in your org, no filtering.
POST /v1/searchesLiveCreates and queues a real sourcing run.
GET /v1/searches/:idLive
GET /v1/searches/:id/candidatesLiveReturns every matched candidate, unfiltered and unpaginated.
GET /v1/candidates/:idLiveIntake details are embedded in this same response, not a separate call.
GET /v1/listsLive
POST /v1/listsLiveCreates an empty list — takes only a name.
Add/remove a candidate on a list via the APIPlannedNot implemented — do this in the app for now.
GET /v1/sequencesLive
GET /v1/sequences/:idLive
POST /v1/sequencesLive, draft-onlyAlways creates a DRAFT. Passing "activate": true is rejected with a 400 — activate it in the app instead.
Pause/activate a sequence via the APIPlanned
List a sequence's enrolled candidates via the APIPlanned
GET /v1/inbox/conversationsLiveNote the path — it's /inbox/conversations, not /inbox.
GET /v1/inbox/conversations/:idLiveFull thread for one candidate.
Send a reply via the APIPlannedRead-only for now.
GET /v1/interviewsLive
POST /v1/interviewsLiveSee the Test/Live warning above — this really sends things.
Reschedule or cancel an interview via the APIPlannedDo this in the app for now.
Webhooks (any event)PlannedNo subscription, signing, or delivery system exists yet — you must poll.
Pagination (limit/cursor)PlannedEvery list endpoint returns its complete result set in one response today.
Rate limitingPlannedNo rate-limit headers or enforcement exist yet — be considerate anyway.
Idempotency-Key headerPlannedA repeated POST creates a second object today — dedupe on your side if that matters to you.

Response shape and conventions

  • No envelope. List endpoints return a plain object keyed by the resource name — e.g. { "searches": [...] }, { "candidates": [...] }, { "lists": [...] }, { "sequences": [...] }, { "conversations": [...] }, { "interviews": [...] } — not a generic data array.
  • Field casing is camelCase throughout (matchScore, linkedinUrl, createdAt), matching the app's own data model exactly — not snake_case.
  • Errors are flat. Every error response is { "error": "A human-readable message" } — a plain string, not a structured object with a type/code/field breakdown. Check the HTTP status code to branch on the kind of error.
  • IDs aren't prefixed by object type — don't assume or parse a prefix.

Example calls

List your searches

curl https://api.thefasthire.com/v1/searches \
  -H "Authorization: Bearer fh_live_yourkeyhere"
{
  "searches": [
    { "id": "abc123", "name": "Senior Backend Engineer", "sourceType": "JOB_DESCRIPTION",
      "createdAt": "2026-09-01T04:11:00.000Z", "updatedAt": "2026-09-01T04:15:00.000Z" }
  ]
}

Create a search

criteria is the same object the app itself builds when you fill out the search form — it's a larger structure than you might expect. searchName, roles, companies, languages, education, location, and keywords are all required (empty arrays/nulls are fine for anything you don't need); skills, experience, companiesTiming, and company are optional and default to empty. At minimum:

curl https://api.thefasthire.com/v1/searches \
  -X POST -H "Authorization: Bearer fh_live_yourkeyhere" \
  -H "Content-Type: application/json" \
  -d '{
    "sourceType": "NATURAL_LANGUAGE",
    "criteria": {
      "searchName": "Senior Backend Engineer",
      "roles": ["Backend Engineer"],
      "companies": [],
      "languages": [],
      "education": {
        "fieldsOfStudy": [], "degreeTypes": [], "institutions": [], "excludedInstitutions": [],
        "minGraduationYear": null, "maxGraduationYear": null, "minEducationLevel": null
      },
      "location": { "radiusKm": 50, "entries": [] },
      "keywords": { "mustHave": ["Go", "Kubernetes"], "niceToHave": ["distributed systems"] }
    }
  }'

sourceType must be "NATURAL_LANGUAGE" or "JOB_DESCRIPTION""MANUAL" isn't accepted through the API today. A successful call returns { "id": "..." } with a 201.

Read a search's matched candidates

curl https://api.thefasthire.com/v1/searches/abc123/candidates \
  -H "Authorization: Bearer fh_live_yourkeyhere"
{
  "candidates": [
    {
      "resultId": "res_1", "candidateId": "cnd_1", "name": "Priya Nair",
      "headline": "Staff Engineer at Canva", "location": "Sydney, Australia",
      "phone": null, "email": "priya@example.com",
      "skills": ["Go", "Kubernetes"], "experience": [ /* ... */ ], "education": [ /* ... */ ],
      "matchScore": 87, "matchReasoning": "Strong backend depth, based in target metro.",
      "percentile": 92
    }
  ]
}

matchScore is 0–100, not 0–1, and there's no tier field — FastHire doesn't sort candidates into named tiers anywhere, in the app or the API.

Create a list, then a draft sequence targeting it

curl https://api.thefasthire.com/v1/lists \
  -X POST -H "Authorization: Bearer fh_live_yourkeyhere" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Q4 backend candidates" }'

Returns { "id": "..." }. There's no API to add candidates to it yet — do that in the app.

Check inbox activity

curl https://api.thefasthire.com/v1/inbox/conversations \
  -H "Authorization: Bearer fh_live_yourkeyhere"

Each conversation includes hasUnread, hasReplied, and intakeStatus (null until the candidate has expressed interest). Fetch one thread's full message history with GET /v1/inbox/conversations/:candidateId.

Schedule an interview

curl https://api.thefasthire.com/v1/interviews \
  -X POST -H "Authorization: Bearer fh_live_yourkeyhere" \
  -H "Content-Type: application/json" \
  -d '{
    "candidateId": "cnd_1",
    "scheduledAt": "2026-09-25T10:00:00Z",
    "timezone": "Asia/Kolkata",
    "durationMinutes": 30
  }'

Remember: this really schedules it. If the recruiter who created the key has Google Calendar or Microsoft Teams connected and no meetingLink was supplied, a real calendar event and meeting link are created automatically, and a confirmation is sent to the candidate.

Handling errors

StatusMeaning
400Malformed body, a field failed validation, or you tried something not supported via the API yet (like activating a sequence).
401Missing, malformed, or revoked API key.
402Your org's search cap for the current billing period would be exceeded.
403The team member who created this key has since been deactivated.
404The object doesn't exist, or belongs to a different org than your key.
500Something failed on FastHire's side.

Every error body is { "error": "message" } — read the message, it's written for humans, not parsed by machines yet.

Revoking a key

Go back to Settings → Developer and select Revoke next to any key. This is immediate and permanent — a revoked key returns 401 on every future request. There's no way to temporarily disable and later re-enable the same key; generate a new one if you need to rotate.

Frequently asked questions

Is there a sandbox I can safely test integration code against?

Not yet. Both Test and Live keys act on your organization's real data — see the warning under "What Test vs. Live actually changes" above.

Can I limit a key to read-only, or to specific objects?

No — every key currently has full read/write access to everything the API exposes for your org. There's no scoping today.

Why does creating a search sometimes return a 402?

Your organization has hit its search cap for the current billing period (this mirrors the same limit enforced in the app). Wait for the next period or check Settings → Billing.

Can I paginate a large list of candidates or searches?

Not yet — every list endpoint returns its full result set in a single response.

Does the full API Reference page match this article?

Not entirely — it documents FastHire's intended future shape for this API, and some of what it shows (pagination, webhooks, structured errors, role-scoped keys) isn't built yet. This article reflects what you can actually call today; treat the reference page as a roadmap.


Last reviewed September 2026, verified directly against the deployed /api/v1 route implementations.