> ## 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 API reference

> API reference for the Recruitee plugin in Corsair: every `recruitee.api.*` operation with its input and output types, taken from the plugin's Zod schemas.

> [!NOTE]
>
> **New to Corsair?** See [API access](https://docs.corsair.dev/concepts/api.md), [authentication](https://docs.corsair.dev/concepts/auth.md), and [error handling](https://docs.corsair.dev/concepts/error-handling).

## Candidates

### create

`candidates.create`

Add a candidate manually and assign them to a published or internal offer at its default stage

**Risk:** `write`

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

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `name` | `string` | Yes | The candidate name. |
| `emails` | `string[]` | No | — |
| `phones` | `string[]` | No | — |
| `social_links` | `string[]` | No | — |
| `links` | `string[]` | No | — |
| `cover_letter` | `string` | No | — |
| `sources` | `string[]` | No | — |
| `remote_cv_url` | `string` | No | A link to a CV hosted elsewhere, instead of an upload. |
| `offer_id` | `number` | No | The offer the candidate is assigned to at its default stage. Recruitee skips the assignment, without an error, when the offer is a draft. |

The record goes under `candidate` and the offer assignment beside it as `offers`.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `candidate` | `object` | Yes | — |

> [accordion] candidate full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   emails?: string[] | null,
>   phones?: string[] | null,
>   social_links?: string[] | null,
>   links?: string[] | null,
>   cover_letter?: string | null,
>   sources?: (string | {
>     id?: number | null,
>     name?: string | null
>   })[] | null,
>   admin_id?: number | null,
>   created_at?: string | null,
>   updated_at?: string | null,
>   last_activity_at?: string | null,
>   my_last_rating?: number | string | null,
>   photo_url?: string | null,
>   cv_url?: string | null,
>   placements?: {
>     id?: number | null,
>     candidate_id?: number | null,
>     offer_id?: number | null,
>     talent_pool_id?: number | null,
>     offer?: {
>       id?: number | null,
>       title?: string | null,
>       kind?: string | null,
>       status?: string | null
>     } | null,
>     stage?: {
>       id?: number | null,
>       name?: string | null
>     } | null,
>     stage_id?: number | null,
>     disqualified?: boolean | null,
>     created_at?: string | null,
>     updated_at?: string | null
>   }[] | null,
>   tags?: (string | {
>     id?: number | null,
>     name?: string | null
>   })[] | null
> }
> ```

***

### delete

`candidates.delete`

Delete a candidate. Recruitee keeps them restorable in its deleted list for 7 days, then removes them

**Risk:** `destructive`

```ts theme={null}
await corsair.recruitee.api.candidates.delete({ candidate_id: 135145 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `candidate_id` | `number` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `success` | `boolean` | Yes | — |
| `candidate_id` | `number` | Yes | — |

***

### get

`candidates.get`

Fetch one candidate with their contact details, stage, status and placements

**Risk:** `read`

```ts theme={null}
await corsair.recruitee.api.candidates.get({ candidate_id: 135145 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `candidate_id` | `number` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `candidate` | `object` | Yes | — |

> [accordion] candidate full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   emails?: string[] | null,
>   phones?: string[] | null,
>   social_links?: string[] | null,
>   links?: string[] | null,
>   cover_letter?: string | null,
>   sources?: (string | {
>     id?: number | null,
>     name?: string | null
>   })[] | null,
>   admin_id?: number | null,
>   created_at?: string | null,
>   updated_at?: string | null,
>   last_activity_at?: string | null,
>   my_last_rating?: number | string | null,
>   photo_url?: string | null,
>   cv_url?: string | null,
>   placements?: {
>     id?: number | null,
>     candidate_id?: number | null,
>     offer_id?: number | null,
>     talent_pool_id?: number | null,
>     offer?: {
>       id?: number | null,
>       title?: string | null,
>       kind?: string | null,
>       status?: string | null
>     } | null,
>     stage?: {
>       id?: number | null,
>       name?: string | null
>     } | null,
>     stage_id?: number | null,
>     disqualified?: boolean | null,
>     created_at?: string | null,
>     updated_at?: string | null
>   }[] | null,
>   tags?: (string | {
>     id?: number | null,
>     name?: string | null
>   })[] | null
> }
> ```

***

### list

`candidates.list`

Search candidates by text, offer, stage, status, department or location, a page at a time

**Risk:** `read`

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

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `limit` | `number` | No | Records per page. Recruitee applies its own default when omitted. |
| `page` | `number` | No | The page to read, 1-based. Defaults to 1. |
| `query` | `string` | No | A free-text search over name, emails, phones, tags, sources, stage, cover letter and CV. |
| `offer_id` | `number` | No | Only candidates on this offer. |
| `stage` | `string` | No | Only candidates in a stage with this name, such as `Applied`. |
| `status` | `string` | No | The candidate status: `qualified`, `disqualified` or `new`. |
| `department_id` | `number` | No | Only candidates on offers in this department. |
| `location_id` | `number` | No | Only candidates on offers at this location. |
| `sort_by` | `string` | No | The column to sort on, such as `created_at`, `candidate_name` or `relevance`. |
| `sort_direction` | `asc \| desc` | No | Defaults to `desc` when `sort_by` is set. |

Calls /search/new/candidates and sends the filters as one filters\_json array; page with `page` and `next_page`.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `candidates` | `object[]` | Yes | — |
| `total` | `number \| null` | Yes | How many records match in total, when the route says. |
| `next_page` | `number \| null` | Yes | Pass as `page` to read the next page; null on the last. |

> [accordion] candidates full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   emails?: string[] | null,
>   phones?: string[] | null,
>   social_links?: string[] | null,
>   links?: string[] | null,
>   cover_letter?: string | null,
>   sources?: (string | {
>     id?: number | null,
>     name?: string | null
>   })[] | null,
>   admin_id?: number | null,
>   created_at?: string | null,
>   updated_at?: string | null,
>   last_activity_at?: string | null,
>   my_last_rating?: number | string | null,
>   photo_url?: string | null,
>   cv_url?: string | null,
>   placements?: {
>     id?: number | null,
>     candidate_id?: number | null,
>     offer_id?: number | null,
>     talent_pool_id?: number | null,
>     offer?: {
>       id?: number | null,
>       title?: string | null,
>       kind?: string | null,
>       status?: string | null
>     } | null,
>     stage?: {
>       id?: number | null,
>       name?: string | null
>     } | null,
>     stage_id?: number | null,
>     disqualified?: boolean | null,
>     created_at?: string | null,
>     updated_at?: string | null
>   }[] | null,
>   tags?: (string | {
>     id?: number | null,
>     name?: string | null
>   })[] | null
> }[]
> ```

***

### update

`candidates.update`

Update a candidate profile: their name, emails, phones or cover letter

**Risk:** `write`

```ts theme={null}
await corsair.recruitee.api.candidates.update({ candidate_id: 135145, name: 'John A. Smith' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `candidate_id` | `number` | Yes | — |
| `name` | `string` | No | — |
| `emails` | `string[]` | No | — |
| `phones` | `string[]` | No | — |
| `cover_letter` | `string` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `candidate` | `object` | Yes | — |

> [accordion] candidate full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   emails?: string[] | null,
>   phones?: string[] | null,
>   social_links?: string[] | null,
>   links?: string[] | null,
>   cover_letter?: string | null,
>   sources?: (string | {
>     id?: number | null,
>     name?: string | null
>   })[] | null,
>   admin_id?: number | null,
>   created_at?: string | null,
>   updated_at?: string | null,
>   last_activity_at?: string | null,
>   my_last_rating?: number | string | null,
>   photo_url?: string | null,
>   cv_url?: string | null,
>   placements?: {
>     id?: number | null,
>     candidate_id?: number | null,
>     offer_id?: number | null,
>     talent_pool_id?: number | null,
>     offer?: {
>       id?: number | null,
>       title?: string | null,
>       kind?: string | null,
>       status?: string | null
>     } | null,
>     stage?: {
>       id?: number | null,
>       name?: string | null
>     } | null,
>     stage_id?: number | null,
>     disqualified?: boolean | null,
>     created_at?: string | null,
>     updated_at?: string | null
>   }[] | null,
>   tags?: (string | {
>     id?: number | null,
>     name?: string | null
>   })[] | null
> }
> ```

***

## Departments

### list

`departments.list`

List the company departments with how many offers each has

**Risk:** `read`

```ts theme={null}
await corsair.recruitee.api.departments.list({});
```

**Input:** *empty object*

Returns every department in one answer. `offers_count` is how many offers the department has.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `departments` | `object[]` | Yes | — |

> [accordion] departments full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   status?: string | null,
>   offers_count?: number | null
> }[]
> ```

***

## Locations

### list

`locations.list`

List the company locations with their city, country and address

**Risk:** `read`

```ts theme={null}
await corsair.recruitee.api.locations.list({});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `limit` | `number` | No | Records per page. Recruitee applies its own default when omitted. |
| `page` | `number` | No | The page to read, 1-based. Defaults to 1. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `locations` | `object[]` | Yes | — |
| `total` | `number \| null` | Yes | How many records match in total, when the route says. |
| `next_page` | `number \| null` | Yes | Pass as `page` to read the next page; null on the last. |

> [accordion] locations full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   city?: string | null,
>   state_name?: string | null,
>   country_code?: string | null,
>   full_address?: string | null,
>   note?: string | null,
>   archived_at?: string | null
> }[]
> ```

***

## Offers

### create

`offers.create`

Create an offer as a draft job or talent pool; publishing is done in Recruitee

**Risk:** `write`

```ts theme={null}
await corsair.recruitee.api.offers.create({ title: 'Senior Backend Engineer', kind: 'job', description: '<p>Build the API.</p>', requirements: '<p>Five years of TypeScript.</p>', location_ids: [2] });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `title` | `string` | Yes | — |
| `kind` | `job \| talent_pool` | No | — |
| `description` | `string` | No | The description, as HTML. |
| `requirements` | `string` | No | The requirements, as HTML. Recruitee requires them for a job. |
| `department_id` | `number` | No | — |
| `location_ids` | `number[]` | No | Location ids from `locations.list`. Recruitee requires at least one for a job. |

A new offer is created as a draft. A job needs description, requirements and location\_ids.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `offer` | `object` | Yes | — |

> [accordion] offer full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   title?: string | null,
>   slug?: string | null,
>   status?: string | null,
>   kind?: string | null,
>   department?: string | null,
>   department_id?: number | null,
>   location?: string | null,
>   location_ids?: number[] | null,
>   city?: string | null,
>   country_code?: string | null,
>   description?: string | null,
>   requirements?: string | null,
>   created_at?: string | null,
>   updated_at?: string | null,
>   published_at?: string | null,
>   translations?: {
>     locale?: string | null,
>     title?: string | null,
>     description?: string | null,
>     requirements?: string | null
>   }[] | null
> }
> ```

***

### get

`offers.get`

Fetch one offer with its title, slug, description, requirements and state

**Risk:** `read`

```ts theme={null}
await corsair.recruitee.api.offers.get({ offer_id: 42 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `offer_id` | `number` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `offer` | `object` | Yes | — |

> [accordion] offer full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   title?: string | null,
>   slug?: string | null,
>   status?: string | null,
>   kind?: string | null,
>   department?: string | null,
>   department_id?: number | null,
>   location?: string | null,
>   location_ids?: number[] | null,
>   city?: string | null,
>   country_code?: string | null,
>   description?: string | null,
>   requirements?: string | null,
>   created_at?: string | null,
>   updated_at?: string | null,
>   published_at?: string | null,
>   translations?: {
>     locale?: string | null,
>     title?: string | null,
>     description?: string | null,
>     requirements?: string | null
>   }[] | null
> }
> ```

***

### list

`offers.list`

List offers with status, department, location and kind filters, a page at a time

**Risk:** `read`

```ts theme={null}
await corsair.recruitee.api.offers.list({ status: 'published', limit: 25 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `limit` | `number` | No | Records per page. Recruitee applies its own default when omitted. |
| `page` | `number` | No | The page to read, 1-based. Defaults to 1. |
| `department_id` | `number` | No | Only offers in this department. |
| `location_id` | `number` | No | Only offers at this location. |
| `status` | `draft \| published \| internal \| closed \| archived` | No | Only offers in this status. |
| `kind` | `job \| talent_pool` | No | `job` for a posted role, `talent_pool` for a pool. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `offers` | `object[]` | Yes | — |
| `total` | `number \| null` | Yes | How many records match in total, when the route says. |
| `next_page` | `number \| null` | Yes | Pass as `page` to read the next page; null on the last. |

> [accordion] offers full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   title?: string | null,
>   slug?: string | null,
>   status?: string | null,
>   kind?: string | null,
>   department?: string | null,
>   department_id?: number | null,
>   location?: string | null,
>   location_ids?: number[] | null,
>   city?: string | null,
>   country_code?: string | null,
>   description?: string | null,
>   requirements?: string | null,
>   created_at?: string | null,
>   updated_at?: string | null,
>   published_at?: string | null,
>   translations?: {
>     locale?: string | null,
>     title?: string | null,
>     description?: string | null,
>     requirements?: string | null
>   }[] | null
> }[]
> ```

***

### update

`offers.update`

Update an offer: its title, description, requirements, department or locations

**Risk:** `write`

```ts theme={null}
await corsair.recruitee.api.offers.update({ offer_id: 42, title: 'Staff Backend Engineer' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `title` | `string` | No | — |
| `kind` | `job \| talent_pool` | No | — |
| `description` | `string` | No | The description, as HTML. |
| `requirements` | `string` | No | The requirements, as HTML. Recruitee requires them for a job. |
| `department_id` | `number` | No | — |
| `location_ids` | `number[]` | No | Location ids from `locations.list`. Recruitee requires at least one for a job. |
| `offer_id` | `number` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `offer` | `object` | Yes | — |

> [accordion] offer full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   title?: string | null,
>   slug?: string | null,
>   status?: string | null,
>   kind?: string | null,
>   department?: string | null,
>   department_id?: number | null,
>   location?: string | null,
>   location_ids?: number[] | null,
>   city?: string | null,
>   country_code?: string | null,
>   description?: string | null,
>   requirements?: string | null,
>   created_at?: string | null,
>   updated_at?: string | null,
>   published_at?: string | null,
>   translations?: {
>     locale?: string | null,
>     title?: string | null,
>     description?: string | null,
>     requirements?: string | null
>   }[] | null
> }
> ```

***


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