> ## Documentation Index
> Fetch the complete documentation index at: https://docs.corsair.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Recruitee plugin

> Applicant tracking with Recruitee - search, read and write candidates, read and write offers, and list the departments and locations they belong to through the Recruitee ATS API.

Use **Recruitee** through Corsair: one client, typed API calls.

Create a token under **Settings → Apps and plugins → Personal API tokens**, then copy the **company id** from the same page. Send the token as `Authorization: Bearer <token>`; every ATS route sits under `/c/{company_id}`. Things to know before you call:

* **The company id is half the credential.** A token belongs to one company, and the id is part of every path. Using a token for another company answers `401`, so the plugin stores both and refuses to build a request without the id.
* **Tokens cannot be regenerated.** Revoking one leaves you creating a new token and updating every integration, so a `401` is terminal; the plugin never retries it. A token also carries its creator's permissions, including removing that user from the company cutting their tokens off from it.
* **Three error shapes exist.** The current one is `{ errors: [{ code, data, message }] }`; the older ATS routes answer `{ error, error_code }`; and the host can answer a bare `401` with no body. The plugin reads whichever arrived.
* **Candidate search takes one `filters_json` array.** `candidates.list` calls `/search/new/candidates` and builds that array from `query`, `offer_id`, `stage`, `status`, `department_id` and `location_id`. The route ignores plain `query` or `offset` parameters, and answers `{ hits, total }`.
* **Offer filters are arrays.** `offers.list` sends `statuses[]`, `department_ids[]` and `location_ids[]`; Recruitee ignores a bare `status` and returns every offer.
* **Creates and updates wrap the record.** A candidate or offer goes in under a `candidate` or `offer` key, and a candidate's offer assignments sit **beside** that key as an `offers` array rather than inside it.
* **Paging is `page` and `limit`.** Candidates, offers and locations return `total` and `next_page` (null on the last page). Departments come back in one answer.
* **A new offer is a draft.** The create and update routes take no status; publishing is a separate step in Recruitee. A job needs `description`, `requirements` and at least one of `location_ids`.
* **Drafts take no candidates.** `candidates.create` with the `offer_id` of a draft offer creates the candidate but places them nowhere, and Recruitee returns no error. Publish the offer first, or assign the candidate later.
* **A candidate delete is restorable for 7 days.** Recruitee sets `deleted_at` a week ahead and keeps the candidate in its deleted list until then.
* **Stages live on placements.** `candidates.update` edits the profile; moving a candidate to another stage or disqualifying them happens on their placement for an offer, which this plugin does not cover yet.
* **Rate limit.** 1000 requests per minute per token. Recruitee documents no `Retry-After`, so a 429 is retried three times with backoff.

**What you get:**

* 11 typed API operations

## Setup

**1. Install**

```bash npm theme={null}
npm install corsair @corsair-dev/recruitee better-sqlite3
npm install --save-dev @types/better-sqlite3
```

```bash yarn theme={null}
yarn add corsair @corsair-dev/recruitee better-sqlite3
yarn add --dev @types/better-sqlite3
```

```bash pnpm theme={null}
pnpm install corsair @corsair-dev/recruitee better-sqlite3
pnpm install --save-dev @types/better-sqlite3
```

```bash bun theme={null}
bun add corsair @corsair-dev/recruitee better-sqlite3
bun add --dev @types/better-sqlite3
```

**2. Add the plugin**

```ts corsair.ts theme={null}
import Database from 'better-sqlite3';
import { createCorsair } from 'corsair';
import { recruitee } from '@corsair-dev/recruitee';

export const corsair = createCorsair({
	plugins: [
		recruitee(),
	],
	database: new Database('corsair.db'),
	kek: process.env.CORSAIR_KEK!,
	multiTenancy: true,
	hub: {
		projectApiKey: process.env.CORSAIR_API_KEY!,
		signingSecret: process.env.CORSAIR_SIGNING_SECRET!,
	},
});
```

With `multiTenancy: true`, scope calls with `corsair.withTenant(id)`. See [Quick start](https://docs.corsair.dev/quick-start.md) for KEK + Hub keys, and [Multi-tenancy](https://docs.corsair.dev/concepts/multi-tenancy.md) for account isolation.

**3. Choose authentication**

> [tab] API Key (Recommended)
>
> No setup required yet. When you make your first request as a tenant, Corsair prompts for the API key.
>
> ```ts theme={null}
> recruitee()
> ```
>
> More: [API Key](https://docs.corsair.dev/concepts/api-key)

**4. Connect a tenant**

Mint a connect link and send the tenant to it. Hub hosts the page and delivers the result to your app — see [Connect / OAuth](https://docs.corsair.dev/management/connect).

```ts theme={null}
const { connectUrl } = await corsair.manage.connect.createLink({
	plugin: 'recruitee',
	tenantId: 'acme',
});
// redirect the user's browser to connectUrl
```

## Example API calls

**Search candidates on one offer**

```ts theme={null}
const tenant = corsair.withTenant('acme');
await tenant.recruitee.api.candidates.list({ offer_id: 42, limit: 25 });
```

**Add a candidate to an offer**

```ts theme={null}
const tenant = corsair.withTenant('acme');
await tenant.recruitee.api.candidates.create({
	name: 'John Smith',
	emails: ['john@example.com'],
	offer_id: 42,
});
```

See the full list on the [API](https://docs.corsair.dev/plugins/recruitee/api.md) page.

## What's next

> [card] [API reference](https://docs.corsair.dev/plugins/recruitee/api.md)
>
> Every `recruitee.api.*` operation with input and output types.

> [card] [Connect / OAuth](https://docs.corsair.dev/management/connect)
>
> createLink, Hub delivery, and tenant connect flows.

> [card] [Use with agents](https://docs.corsair.dev/mcp-adapters/mcp-adapters)
>
> Expose this plugin's operations as MCP tools.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.