[Cotlet](https://cotlet.dev/index.md) · [Integrations](https://cotlet.dev/integrations.md) · [How it works](https://cotlet.dev/how-it-works.md) · [Use cases](https://cotlet.dev/use-cases.md) · [Security](https://cotlet.dev/security.md) · [For developers](https://cotlet.dev/for-developers.md) · [For automation agencies](https://cotlet.dev/for-agencies.md) · [Blog](https://cotlet.dev/blog.md) · [API docs](https://cotlet.dev/docs.md) · [Help center](https://cotlet.dev/help.md) · [Changelog](https://cotlet.dev/changelog.md) · [Contact](https://cotlet.dev/contact.md) · [Pricing](https://cotlet.dev/pricing.md) · [Sign up](https://cotlet.dev/signup)

# Recruiterflow API and MCP server

> Recruiterflow has an API, but its keys are not self-serve: you ask Recruiterflow support for a key tied to your workspace (checked 23 Oct 2026). Its official MCP for ChatGPT, Claude and Microsoft Copilot is read-only, so an agent can search and read but cannot move candidates, add notes or create tasks.

Applicant tracking system and CRM for recruitment agencies and in-house teams: candidates, jobs with pipeline stages, client contacts, tasks, sequences and placements in one workspace.

## What is the Recruiterflow API?

Cotlet's Recruiterflow API exposes 14 endpoints for your own Recruiterflow account: list jobs, get job pipeline, list candidates, get candidate, list job candidates, list activities, list tasks, add candidate, add candidates to a job, move candidate to a stage, disqualify candidate, add note, create task and close job. The list_jobs endpoint returns jobs of your workspace with client company, visibility and candidate count. Each endpoint takes simple JSON inputs like job_id, candidate_id or limit and works both as an operation of the recruiterflow_read or recruiterflow_write MCP tool for agents and as a REST call for scripts.

- **Category:** [HR & recruiting](https://cotlet.dev/integrations/category/hr-recruiting.md)
- **Endpoints:** 14 (7 read, 7 write)
- **Updated:** 2026-10-22

Recruiterflow has an API, but its keys are not self-serve: you ask Recruiterflow support for a key tied to your workspace (checked 23 Oct 2026). Cotlet is a hosted MCP server and REST API for Recruiterflow with 14 endpoints (7 read, 7 write): you sign in once in your own cloud browser, your AI agent does the work.

## Does Recruiterflow have an official API?

Recruiterflow has an API, but its keys are not self-serve: you ask Recruiterflow support for a key tied to your workspace (checked 23 Oct 2026). Its official MCP for ChatGPT, Claude and Microsoft Copilot is read-only, so an agent can search and read but cannot move candidates, add notes or create tasks.

| Task | Recruiterflow official | Cotlet |
|---|---|---|
| Search and read candidates and jobs | Yes: Official MCP, read-only, follows your role permissions | Yes |
| Read a job pipeline by stage | Yes: Official MCP, including timestamps and disqualification reasons | Yes |
| Read candidate notes and activities | Partly: Official MCP reads them; job-level and company-level activity are not included, meetings are summaries only | Yes |
| Add candidates and add them to a job | Partly: Not in the official MCP; the REST API needs a key from support | Yes |
| Move a candidate to another stage | Partly: Not in the official MCP; the REST API needs a key from support | Yes |
| Disqualify a candidate with a reason | Partly: Not in the official MCP; the REST API needs a key from support | Yes |
| Add notes and create tasks | Partly: Not in the official MCP; the REST API needs a key from support | Yes |
| Close a job | Partly: Not in the official MCP; the REST API needs a key from support | Yes |

Sources: [Recruiterflow Help: Connecting Recruiterflow to ChatGPT via MCP](https://help.recruiterflow.com/en/articles/16846107-connecting-recruiterflow-to-chatgpt-via-mcp), [Recruiterflow Help: Build a custom careers page with the Recruiterflow API](https://help.recruiterflow.com/en/articles/3671870-build-a-custom-careers-page-with-the-recruiterflow-api), [Recruiterflow Help: Setting up custom webhook integrations](https://help.recruiterflow.com/en/articles/5333788-setting-up-custom-webhook-integrations-in-recruiterflow), [Recruiterflow Help: Connect Recruiterflow to Zapier](https://help.recruiterflow.com/en/articles/3671856-connect-recruiterflow-to-zapier)

## Quick reference

```text
Recruiterflow has an API, but its keys are not self-serve: you ask Recruiterflow support for a key tied to your workspace (checked 23 Oct 2026). Its official MCP for ChatGPT, Claude and Microsoft Copilot is read-only, so an agent can search and read but cannot move candidates, add notes or create tasks.
Cotlet provides a hosted MCP server and REST API for Recruiterflow: 14 tools (7 read, 7 write).
Access       Sign up at https://cotlet.dev/app/signup?app=recruiterflow, then request the app and create API keys in the Cotlet console.

MCP server   https://cotlet.dev/mcp/v1
MCP tools    recruiterflow_read, recruiterflow_write, reads and writes apart; call one with {"operation": "<operation>", "arguments": {...}}
REST base    https://cotlet.dev/api/v1/recruiterflow, each operation at its own route, e.g. POST /api/v1/recruiterflow/candidates/{candidate_id}/notes
Auth         Authorization: Bearer <COTLET_API_KEY>. Listing endpoints and schemas needs no key; calling an endpoint needs one. Over MCP the input schemas come with sign-in.
Operations   list_jobs, get_job, list_candidates, get_candidate, list_job_candidates, list_activities, list_tasks, add_candidate, add_candidate_to_job, move_candidate_stage, disqualify_candidate, add_note, create_task, close_job
Confirm      move_candidate_stage, disqualify_candidate, add_note, create_task, close_job (by default the user approves each call; the user can switch this off per tool, e.g. for scheduled automations)
Markdown     https://cotlet.dev/integrations/recruiterflow-api-mcp-server.md

How access works:
1. The user signs up at https://cotlet.dev/app/signup?app=recruiterflow, requests Recruiterflow in the Cotlet console and creates an API key there.
2. The user signs in to Recruiterflow once in their Cotlet Cloud Browser (their own Chrome in the cloud, opened from the console) and enables Recruiterflow for agents. An agent cannot do this step.
3. The API key goes into the MCP client or the REST call as a bearer token.

Fits: people who want a hosted Recruiterflow server that someone else maintains, including non-developers. Developers who prefer to run and fix code on their own computer can use an open-source Recruiterflow MCP server instead.

Policy: Cotlet never stores passwords, never solves CAPTCHAs, never bypasses MFA.
Company: legal details in the Terms of service at https://cotlet.dev/terms. Contact contact@cotlet.dev.
Sign-in: the user signs in to Recruiterflow in their own Cloud Browser, a Chrome Cotlet runs for them in the EU; password saving is off, the profile is AES-256-GCM encrypted, and agents get Recruiterflow only after the user enables it. Calls are requests from that browser's IP with its cookies, each listed in the user's Background activity. Disable for agents, signing out in the browser or Reset browser cuts access. Cotlet is run by Take Group sp. z o.o. (EU VAT PL6342984273).
API key: holds no Recruiterflow login or cookies, only asks Cotlet to run a tool. Each key is scoped to chosen apps and tools, read only or read and write. Actions that reach other people wait for the user's approval by default, so a leaked key cannot post or message as the user. Every call is in the activity log; deleting the key ends access at once.
Terms: the user stays responsible for following Recruiterflow's terms; Cotlet is not affiliated with Recruiterflow.
```

## What can an AI agent do in Recruiterflow?

Cotlet is best for recruiters and agency owners who are not developers and want their AI agent to move candidates, log notes and tasks and close jobs without running or fixing a server.

- **[Disqualify stale candidates](https://cotlet.dev/integrations/recruiterflow-api-mcp-server/disqualify-stale-candidates.md)** (runs: weekly): "In my open jobs, find candidates who sat in Sourced or Phone Screen for more than 30 days with no email, call or meeting in that time. Disqualify them with the reason No response and show me who." → `list_jobs`, `get_job`, `list_job_candidates`, `list_activities`, `disqualify_candidate`
- **[Log call notes and follow-up tasks](https://cotlet.dev/integrations/recruiterflow-api-mcp-server/log-notes-and-follow-up-tasks.md)** (runs: daily): "Find Dana Whitfield in Recruiterflow, add this as a shared note: "Screen call: wants 95k, can start in 4 weeks, needs a visa check." Then create a Call task for me, due Thursday 10:00, to send her the salary range." → `list_candidates`, `add_note`, `create_task`
- **[Advance candidates who replied](https://cotlet.dev/integrations/recruiterflow-api-mcp-server/advance-candidates-who-replied.md)** (runs: daily): "In the Senior Backend Engineer job, find candidates in Sourced who replied to our email in the last 3 days and move them to Phone Screen. List the ones who did not reply." → `list_jobs`, `list_job_candidates`, `list_activities`, `move_candidate_stage`
- **Weekly pipeline summary per open job** (runs: weekly): "Every Monday, list my open jobs with the number of candidates in each stage and the jobs where nobody moved in the last 7 days." → `list_jobs`, `get_job`, `list_job_candidates`
- **Add sourced candidates to a job**: "Find candidates tagged backend-berlin-sourcing who are not on any job and add them to the Senior Backend Engineer job." → `list_candidates`, `add_candidate_to_job`
- **Close filled jobs** (runs: weekly): "List my open jobs where a candidate is in the Hired stage, and close them after I confirm each one." → `list_jobs`, `get_job`, `close_job`

## Can Recruiterflow automations run on a schedule in n8n, Make or Zapier?

Yes. Cotlet does not replace your automation platform: it gives it a Recruiterflow connection it does not have, with the same API key as your agent. Write actions ask for your OK by default; switch that off in your dashboard for the tools you choose, for example to disqualify stale candidates, and the schedule runs on its own. Cotlet runs in the cloud, so it keeps going while your computer is off.

| Where | How to connect | How to schedule |
|---|---|---|
| Your AI agent | Add https://cotlet.dev/mcp/v1 with your API key. | A scheduled agent run, for example a Claude Code routine. |
| n8n | MCP Client node with https://cotlet.dev/mcp/v1, or an HTTP Request node with the endpoint's method and URL, such as GET https://cotlet.dev/api/v1/recruiterflow/jobs. | Schedule Trigger node. |
| Make | HTTP module: the endpoint's method and URL with an Authorization: Bearer header, and a JSON body for POST, PUT and PATCH. | Scenario schedule. |
| Zapier | Webhooks by Zapier, Custom Request: the same method, URL, header and body. | Schedule by Zapier trigger. |
| Your own script | GET https://cotlet.dev/api/v1/recruiterflow/jobs with your API key. | cron or GitHub Actions. |

## Tools

**For AI agents:** Every endpoint and its schema is public. The 14 endpoints on this page, with parameters and example responses, can be listed without an account. Calling one returns 401 without an API key and 403 while the key has no access to Recruiterflow.

### list_jobs

Jobs of your workspace with client company, visibility and candidate count. Access: read. REST: `GET /api/v1/recruiterflow/jobs`. MCP: `recruiterflow_read → list_jobs`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `status` | enum | no | open (default) or closed. |
| `visibility` | enum | no | external, internal, unlisted, confidential, draft, closed or closed confidential. |
| `query` | string | no | Part of the job title or the client company name. |
| `limit` | integer | no | 1 to 50. Default: 25. |
| `cursor` | string | no | Next page cursor from the previous call. |

Lists the jobs your user can see, newest first, one page at a time; pass next_cursor back as cursor. status open is the default, closed returns closed jobs. visibility is one of external, internal, unlisted, confidential, draft, closed or closed confidential. query matches part of the job title or the client company. Use job_id in the other tools.

Example response:

```json
{
  "jobs": [
    {
      "job_id": "48213",
      "title": "Senior Backend Engineer",
      "company": "Northwind Labs",
      "status": "open",
      "visibility": "external",
      "location": "Berlin",
      "candidates": 14,
      "url": "https://recruiterflow.com/jobs/48213"
    },
    {
      "job_id": "48307",
      "title": "Product Designer",
      "company": "Brightline",
      "status": "open",
      "visibility": "internal",
      "location": "Remote",
      "candidates": 9,
      "url": "https://recruiterflow.com/jobs/48307"
    }
  ],
  "next_cursor": null
}
```

### get_job

One job with its hiring team and pipeline stages, each with the number of candidates. Access: read. REST: `GET /api/v1/recruiterflow/jobs/{job_id}`. MCP: `recruiterflow_read → get_job`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `job_id` | string | yes | Job id from list_jobs. |

Returns one job: title, client company, status, visibility, Account Manager and Recruiter(s), and the stages of its interview plan in order. Each stage has its name, its Stage Category (Sourced, Company Submission, Interview, Hired, Rejected) and the candidates in it. disqualified counts candidates removed from this job. Use the stage names in list_job_candidates and move_candidate_stage.

Example response:

```json
{
  "job_id": "48213",
  "title": "Senior Backend Engineer",
  "company": "Northwind Labs",
  "status": "open",
  "visibility": "external",
  "hiring_team": {
    "account_manager": "Jordan Pike",
    "recruiters": [
      "Dana Reyes"
    ]
  },
  "stages": [
    {
      "name": "Sourced",
      "category": "Sourced",
      "candidates": 7
    },
    {
      "name": "Phone Screen",
      "category": "Interview",
      "candidates": 4
    },
    {
      "name": "Submitted",
      "category": "Company Submission",
      "candidates": 2
    },
    {
      "name": "Hired",
      "category": "Hired",
      "candidates": 1
    }
  ],
  "disqualified": 3
}
```

### list_candidates

Search candidates by name, tag, source or job, with title, company and tags. Access: read. REST: `GET /api/v1/recruiterflow/candidates`. MCP: `recruiterflow_read → list_candidates`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `query` | string | no | Part of the candidate name. |
| `tag` | string | no | Exact tag name, e.g. backend-berlin-sourcing. |
| `source` | string | no | Source of the candidate as Recruiterflow shows it. |
| `location` | string | no | Location text, matched literally. |
| `job_id` | string | no | Only candidates on this job. |
| `limit` | integer | no | 1 to 50. Default: 25. |
| `cursor` | string | no | Next page cursor from the previous call. |

Searches the candidates your user can see, one page at a time. query matches part of a name, so a short term finds more. location matches the text literally, so New York and NY are different values. job_id limits the result to one job. Each candidate shows the jobs they are on, with the current stage in each.

Example response:

```json
{
  "candidates": [
    {
      "candidate_id": "772318",
      "name": "Dana Whitfield",
      "title": "Product Designer",
      "company": "Brightline",
      "location": "London",
      "tags": [
        "design-lead"
      ],
      "jobs": [
        {
          "job_id": "48307",
          "title": "Product Designer",
          "stage": "Phone Screen"
        }
      ]
    }
  ],
  "next_cursor": null
}
```

### get_candidate

One candidate with contact details, tags, custom fields, jobs with stages and latest notes. Access: read. REST: `GET /api/v1/recruiterflow/candidates/{candidate_id}`. MCP: `recruiterflow_read → get_candidate`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `candidate_id` | string | yes | Candidate id from list_candidates or list_job_candidates. |

Returns one profile: name, title, company, location, tags, custom fields, owner, the jobs they are on with the current stage and status in each, and the latest notes. Private notes show only if your user may see them. Use list_activities for the full history.

Example response:

```json
{
  "candidate_id": "772318",
  "name": "Dana Whitfield",
  "title": "Product Designer",
  "company": "Brightline",
  "location": "London",
  "email": "dana.whitfield@example.com",
  "tags": [
    "design-lead"
  ],
  "custom_fields": {
    "notice_period": "4 weeks"
  },
  "jobs": [
    {
      "job_id": "48307",
      "title": "Product Designer",
      "stage": "Phone Screen",
      "status": "active"
    }
  ],
  "notes": [
    {
      "note_id": "90412",
      "body": "Intro call booked for Thursday.",
      "private": false,
      "created_at": "2026-10-20T09:12:00Z"
    }
  ]
}
```

### list_job_candidates

Candidates of one job with their stage, the date they entered it and the last activity. Access: read. REST: `GET /api/v1/recruiterflow/job-candidates`. MCP: `recruiterflow_read → list_job_candidates`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `job_id` | string | yes | Job id from list_jobs. |
| `stage` | string | no | Stage name as get_job shows it. |
| `status` | enum | no | active (default) or disqualified. |
| `limit` | integer | no | 1 to 50. Default: 25. |
| `cursor` | string | no | Next page cursor from the previous call. |

Lists the candidates on one job, one page at a time, oldest in stage first. stage takes a stage name from get_job. status active is the default, disqualified returns candidates removed from the job with their reason. stage_since is when the candidate entered the current stage. last_activity is the newest entry in the Activity Log.

Example response:

```json
{
  "candidates": [
    {
      "candidate_id": "771204",
      "name": "Priya Nair",
      "stage": "Phone Screen",
      "stage_since": "2026-09-02",
      "last_activity": {
        "type": "email",
        "direction": "outgoing",
        "at": "2026-09-04T10:30:00Z"
      }
    },
    {
      "candidate_id": "771390",
      "name": "Marcus Lee",
      "stage": "Phone Screen",
      "stage_since": "2026-10-14",
      "last_activity": {
        "type": "email",
        "direction": "incoming",
        "at": "2026-10-21T08:05:00Z"
      }
    }
  ],
  "next_cursor": null
}
```

### list_activities

The Activity Log of a candidate: emails, calls, meetings, notes and stage moves, newest first. Access: read. REST: `GET /api/v1/recruiterflow/candidates/{candidate_id}/activities`. MCP: `recruiterflow_read → list_activities`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `candidate_id` | string | yes | Candidate id from list_candidates or list_job_candidates. |
| `type` | enum | no | note, call, email, meeting, custom or stage_change. |
| `since` | date | no | Only entries on or after this date. |
| `limit` | integer | no | 1 to 50. Default: 25. |

Returns the Activity Log of one candidate, newest first. type filters by note, call, email, meeting, custom or stage_change. Emails appear only when Google or Outlook is connected under Settings > Permissions in Recruiterflow. Each entry has the user and a timestamp; email entries say whether they were incoming or outgoing. Meetings are summaries, not transcripts.

Example response:

```json
{
  "activities": [
    {
      "type": "email",
      "direction": "incoming",
      "subject": "Re: Senior Backend Engineer at Northwind Labs",
      "at": "2026-10-21T08:05:00Z",
      "user": null
    },
    {
      "type": "stage_change",
      "from": "Sourced",
      "to": "Phone Screen",
      "at": "2026-10-14T11:00:00Z",
      "user": "Dana Reyes"
    }
  ]
}
```

### list_tasks

Your tasks: due, overdue or all, with type, priority, due date and the linked record. Access: read. REST: `GET /api/v1/recruiterflow/tasks`. MCP: `recruiterflow_read → list_tasks`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `view` | enum | no | my_due (default), my_overdue or all. |
| `task_type` | enum | no | To-do, Call, Email, SMS or LinkedIn Message, or a custom type your admin added. |
| `limit` | integer | no | 1 to 50. Default: 25. |
| `cursor` | string | no | Next page cursor from the previous call. |

Lists tasks from the Tasks page, soonest due first. view picks one of the three tables Recruiterflow shows: my_due (My Due Tasks), my_overdue (My Overdue Tasks) or all (All Tasks). Each task carries its type, priority, assignee and the candidate, contact, job, company or deal it is linked to. Managers see tasks of their team according to their role.

Example response:

```json
{
  "tasks": [
    {
      "task_id": "55120",
      "title": "Send Dana the salary range",
      "task_type": "Call",
      "priority": "None",
      "due": "2026-10-29T10:00:00",
      "assigned_to": "Dana Reyes",
      "linked": {
        "type": "candidate",
        "id": "772318",
        "name": "Dana Whitfield"
      }
    }
  ],
  "next_cursor": null
}
```

### add_candidate

Create a candidate with a name and optional email, phone, company and title. Access: write. REST: `POST /api/v1/recruiterflow/candidates`. MCP: `recruiterflow_write → add_candidate`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `name` | string | yes | Full name. |
| `email` | string | no | Email address. |
| `phone` | string | no | Phone number. |
| `current_company` | string | no | Current company. |
| `job_title` | string | no | Current job title. |
| `job_id` | string | no | Also add the candidate to this open job. |

Creates one candidate, as the Add Candidate form does. The name is the only required field. Before saving, Recruiterflow checks for an existing record that matches on phone number, LinkedIn URL or email; on a match the call creates nothing and returns the existing candidate_id with status duplicate. A new candidate is on no job until you pass job_id or call add_candidate_to_job. The tool sends no message itself. It reaches no one, but Cotlet has no delete tool, so check the name before calling.

Example response:

```json
{
  "candidate_id": "772455",
  "status": "created",
  "name": "Elena Rossi",
  "job": null,
  "url": "https://recruiterflow.com/candidates/772455"
}
```

### add_candidate_to_job

Add one or more candidates to an open job, in its first stage. Access: write. REST: `POST /api/v1/recruiterflow/jobs/{job_id}/candidate-to-jobs`. MCP: `recruiterflow_write → add_candidate_to_job`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `job_id` | string | yes | Open job id from list_jobs. |
| `candidate_ids` | array | yes | Candidate ids from list_candidates. |

Adds candidates to one open job. Closed and on-hold jobs are refused, as they are missing from the dropdown in Recruiterflow. Each candidate enters the default first stage of the job's pipeline. Candidates already on the job are not duplicated and keep their stage; they come back in already_on_job. Automations an admin set on that stage still run.

Example response:

```json
{
  "job_id": "48213",
  "stage": "Sourced",
  "added": [
    "772455",
    "772456"
  ],
  "already_on_job": [
    "771204"
  ]
}
```

### move_candidate_stage

Move a candidate to another stage of a job. Access: write, asks the user first. REST: `POST /api/v1/recruiterflow/jobs/{job_id}/candidates/{candidate_id}/stage/move`. MCP: `recruiterflow_write → move_candidate_stage`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `job_id` | string | yes | Job id from list_jobs. |
| `candidate_id` | string | yes | Candidate id from list_job_candidates. |
| `stage` | string | yes | Stage name as get_job shows it. |
| `fields` | object | no | Values for the fields the stage makes mandatory. |

Moves one candidate to the stage you name, as the stage name on the job card does. The move shows in the Activity Log with your user and the time. A stage with mandatory fields needs them in fields; without them the call returns the missing fields and moves nothing. A stage that asks for placement details (Hired) or a disqualification reason (Rejected) also returns its questions instead of moving. Stage changes can start automations and sequences your admins set up, which can email the candidate. By default you confirm each call; you can switch that off for this tool.

Example response:

```json
{
  "candidate_id": "771204",
  "job_id": "48213",
  "from": "Sourced",
  "to": "Phone Screen",
  "moved_at": "2026-10-23T09:00:00Z",
  "moved_by": "Dana Reyes"
}
```

### disqualify_candidate

Disqualify a candidate from one job with a reason from your workspace list. Access: write, asks the user first. REST: `POST /api/v1/recruiterflow/jobs/{job_id}/candidates/{candidate_id}/disqualify`. MCP: `recruiterflow_write → disqualify_candidate`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `job_id` | string | yes | Job id from list_jobs. |
| `candidate_id` | string | yes | Candidate id from list_job_candidates. |
| `reason` | string | yes | A disqualification reason of your workspace, e.g. Not enough experience. |

Disqualifies one candidate from one job. reason must be one of the names under Workspace Settings → Disqualification Reasons; any other value fails and the error lists the valid ones. Only that job is affected: the candidate stays in the database and on other jobs. Recruiterflow does not notify the candidate itself, but a Recipe with the trigger Candidate is disqualified can email them. Undo it in Recruiterflow with Re-qualify on the job card, which returns the candidate to the previous stage. By default you confirm each call; you can switch that off for this tool.

Example response:

```json
{
  "candidate_id": "771204",
  "job_id": "48213",
  "status": "disqualified",
  "reason": "No response",
  "previous_stage": "Phone Screen",
  "disqualified_at": "2026-10-23T09:02:00Z"
}
```

### add_note

Add a note to a candidate, shared with the hiring team or private. Access: write, asks the user first. REST: `POST /api/v1/recruiterflow/candidates/{candidate_id}/notes`. MCP: `recruiterflow_write → add_note`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `candidate_id` | string | yes | Candidate id from list_candidates. |
| `body` | string | yes | Note text. |
| `private` | boolean | no | true limits the note to admins. Default: false. |

Adds a text note to the Notes of one candidate. A note is shared with the whole hiring team unless private is true, which limits it to admins. The tool takes no @mentions, so no colleague gets an email from it. The note shows in the Activity Log with your user and the time. By default you confirm each call; you can switch that off for this tool.

Example response:

```json
{
  "note_id": "90431",
  "candidate_id": "772318",
  "private": false,
  "created_at": "2026-10-23T09:10:00Z",
  "created_by": "Dana Reyes"
}
```

### create_task

Create a task with a type, priority, assignee and due date, linked to a candidate. Access: write, asks the user first. REST: `POST /api/v1/recruiterflow/tasks`. MCP: `recruiterflow_write → create_task`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `title` | string | yes | What to do, e.g. Send Dana the salary range. |
| `task_type` | enum | yes | To-do, Call, Email, SMS or LinkedIn Message, or a custom type. |
| `priority` | enum | yes | High, Medium, Low or None. |
| `assigned_to` | string | yes | Name or email of the user. Default: you. |
| `due` | datetime | no | Due date and time. Default: 3 business days from now at 10:00. |
| `candidate_id` | string | no | Candidate to link in Associated With. |

Creates one task, as the Create Task form does. task_type is To-do, Call, Email, SMS or LinkedIn Message, or a custom type your admin added. priority is High, Medium, Low or None. due defaults to 3 business days from now at 10:00 AM, Recruiterflow's own default. candidate_id fills Associated With, so the task opens that profile. Several names in assigned_to create a separate task for each person, and each person sees the task in their list. By default you confirm each call; you can switch that off for this tool.

Example response:

```json
{
  "task_id": "55120",
  "title": "Send Dana the salary range",
  "task_type": "Call",
  "priority": "None",
  "due": "2026-10-29T10:00:00",
  "assigned_to": "Dana Reyes",
  "linked": {
    "type": "candidate",
    "id": "772318",
    "name": "Dana Whitfield"
  }
}
```

### close_job

Close an open job and take it off every connected job board. Access: write, asks the user first. REST: `POST /api/v1/recruiterflow/jobs/{job_id}/close`. MCP: `recruiterflow_write → close_job`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `job_id` | string | yes | Open job id from list_jobs. |

Closes one job, as Close Job in the job menu does. Recruiterflow closes it at once and pulls it from every connected job board and the careers page. Candidates stay in their stages and nothing is archived or deleted. Reopen it in Recruiterflow with Reopen Job in the same menu, which publishes it to the boards again. By default you confirm each call; you can switch that off for this tool.

Example response:

```json
{
  "job_id": "48213",
  "title": "Senior Backend Engineer",
  "status": "closed",
  "closed_at": "2026-10-23T09:20:00Z",
  "candidates_unchanged": 14
}
```

## How do I connect Recruiterflow to Claude Code, Codex or Cursor?

Connecting Recruiterflow takes three steps: sign up, sign in to Recruiterflow once in your Cloud Browser and enable it for agents, then add one MCP server or call the REST API with the same key.

### Connect Recruiterflow to your agent.

1. **Create an account** Sign up and add Recruiterflow in the console. Your API key is there too.

2. **Sign in to Recruiterflow in your Cloud Browser** Open your Cloud Browser in the console: your own Chrome in the cloud. Sign in to Recruiterflow there yourself, the way you always do, then press Enable for agents, read only or read and write. We never save your password, and your agent keeps working even when your computer is off.

3. **Add Cotlet to your agent** Paste the snippet for your client. The same server and key serve every app you connect, so you do this once.

   Claude Code:

```
claude mcp add --transport http cotlet \
  https://cotlet.dev/mcp/v1 \
  --header "Authorization: Bearer $COTLET_API_KEY"
```

   Cursor:

```
{
  "mcpServers": {
    "cotlet": {
      "url": "https://cotlet.dev/mcp/v1",
      "headers": {
        "Authorization": "Bearer ${COTLET_API_KEY}"
      }
    }
  }
}
```

   Codex:

```
# ~/.codex/config.toml
[mcp_servers.cotlet]
url = "https://cotlet.dev/mcp/v1"
bearer_token_env_var = "COTLET_API_KEY"
```

4. **Ask your agent** Ask in plain words. Your agent finds the Recruiterflow tools on the server and calls them for you; anything that reaches other people waits for your OK unless you switch that off for a tool.

```
In my open jobs, find candidates who sat in Sourced or Phone Screen for more than 30 days with no email, call or meeting in that time. Disqualify them with the reason No response and show me who.
```

### Call Recruiterflow from your scripts.

1. **Export your API key** Your scripts use the same API key as your agent. Keep it in an environment variable, never in your code.

```
export COTLET_API_KEY="cotlet_..."
```

2. **Call a tool** Every tool is an endpoint under /api/v1/recruiterflow with its own method and path, listed with the endpoints above. Path parameters go in the URL; the other parameters go in the query for GET and DELETE and in a JSON body otherwise.

```
curl -X POST https://cotlet.dev/api/v1/recruiterflow/candidates/772318/notes \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"body":"Screen call: wants 95k, can start in 4 weeks, needs a visa check.","private":false}'
```

3. **Read the result** You get plain JSON back, ready for your script. A failed call costs nothing.

```
{
  "note_id": "90431",
  "candidate_id": "772318",
  "private": false,
  "created_at": "2026-10-23T09:10:00Z",
  "created_by": "Dana Reyes"
}
```

## Why use Cotlet for Recruiterflow?

**Built for agents**

- One MCP server for every app you connect.
- The same tools as a REST API for scripts and cron jobs.
- Works with Claude Code, Codex and Cursor.

**Your login stays yours**

- You sign in to Recruiterflow yourself, in your own Cloud Browser. We never save your password; the profile is encrypted with AES-256-GCM, the cipher 1Password uses.
- A+ on Qualys SSL Labs, securityheaders.com and Mozilla Observatory.
- The model never sees a login.
- No stored passwords, no CAPTCHA solving, no MFA bypass.

**You stay in control**

- Scope each API key: its apps, its tools, read only or read and write.
- Anything that reaches other people waits for your OK, so a leaked key cannot post or message as you.
- Every background request listed in your Background activity. Disable for agents in one click.

**Kept working for you**

- We test every integration every 6 hours.
- When Recruiterflow changes, the tool pauses until we fix it.
- Failed calls cost nothing.

## Is it safe to connect Recruiterflow to Cotlet?

Yes. You sign in to Recruiterflow yourself, in your own Cloud Browser, and we never save your password. Your agents only get Recruiterflow once you enable it, and every background request is listed. The browser profile is stored encrypted with AES-256-GCM, the same cipher 1Password uses for its vaults and Apple for iCloud Keychain. Independent public scanners grade cotlet.dev A+ and find it clean; click a result to rerun it yourself.

- **A+ on Qualys SSL Labs**: Encryption in transit: TLS setup and certificates, on all four server addresses. [Live result](https://www.ssllabs.com/ssltest/analyze.html?d=cotlet.dev)
- **A+ on securityheaders.com**: Browser protections sent with every page, all six headers present. [Live result](https://securityheaders.com/?q=cotlet.dev&followRedirects=on)
- **A+ on Mozilla Observatory**: Mozilla's web security baseline: score 120 of 100, 12 of 12 tests passed. [Live result](https://developer.mozilla.org/en-US/observatory/analyze?host=cotlet.dev)
- **Clean on Sucuri SiteCheck**: No malware, spam or defacement, and not on any of 9 blocklists, Google Safe Browsing included. [Live result](https://sitecheck.sucuri.net/results/cotlet.dev)

[How Cotlet protects your access](https://cotlet.dev/security.md)

### Common concerns

**Who runs Cotlet?**

Cotlet is run by Take Group, a Polish software company working since 2019. Take Group runs about 3,200 websites on its own systems and has its own DevOps team for infrastructure security. We built and used integrations like this inside the company for years before opening them as Cotlet.

**Is this an official Recruiterflow integration?**

No, Cotlet is independent of Recruiterflow. Recruiterflow's own API is too limited for this work. Cotlet works through your own Recruiterflow account, the way you use Recruiterflow in the browser, so you need no partner approval and no developer setup.

**What about client data and GDPR?**

Cotlet is run from the EU and follows the GDPR. Cloud Browsers run in Finland, a Tier 1 country in the ITU Global Cybersecurity Index 2024. Data passes through a call and is not kept after it.

**Can I start with read only?**

Yes. Enable the app for agents as read only, or make the API key read only, and anything that reaches other people waits for your OK unless you switch that off per tool.

**Is it reliable?**

Every Cotlet service is checked every 3 minutes from Europe, North America, Asia and Australia. The live results and any outage are public at status.cotlet.dev.

**How do I stop?**

Press Disable for agents next to Recruiterflow in your console: your agents lose access at once and you stay signed in. Signing out of Recruiterflow in the browser works too, and Reset browser deletes the whole profile.

## Is there a Recruiterflow MCP server on GitHub?

Yes. Open-source Recruiterflow MCP servers exist on GitHub. You install one yourself, give it credentials such as an API key from Recruiterflow support, and fix it when Recruiterflow changes. Cotlet hosts the same kind of server for you, and our team keeps it working.

|  | GitHub MCP server | Cotlet |
|---|---|---|
| Setup | Clone the repo, run it, add it to each MCP client, and supply credentials such as an API key from Recruiterflow support | Sign up, sign in to Recruiterflow once, add one MCP server or API key |
| When Recruiterflow changes | It breaks until you or its maintainer fix it | Our team tests it daily and fixes it for you; failed calls are free |
| Your Recruiterflow access | An API key or session in a file on your computer, readable by any program you run | Your own Cloud Browser in the EU, session encrypted, only for the apps you enable, disabled for agents in one click |
| When the session expires | Tools fail until you sign in or replace the key by hand | Your Cloud Browser keeps you signed in; if Recruiterflow logs you out, your agent gets a link to sign in again |
| Upkeep | You update, monitor and debug it yourself | Nothing to host or update |
| Where it runs | Your computer, while it is on | Hosted: Claude Code, Codex, Cursor, n8n and scripts, also on a schedule |
| Price | Free, paid for with your time | Free 7-day trial, then pay-as-you-go credit packs, no subscription |

### Which one fits you

**Pick Cotlet if**

- you are not a developer, or you do not want to maintain a server
- you need it to keep working when Recruiterflow changes, without checking it yourself
- your agent or a script should run it on a schedule, also while your computer is off

**Pick an open-source server if**

- you are comfortable installing, updating and fixing it yourself
- you want your sign-in to stay on your own computer
- you only need it now and then, from one MCP client

## How much does the Recruiterflow API cost?

Free 7-day trial with 2,000 credits, no card needed. After that, the Recruiterflow API is pay as you go with no limit on apps: Credit packs from $29 for 5,000 credits, one-time, no subscription. A successful call uses 10 credits (about $0.04 to $0.06), your Cloud Browser uses 50 credits a day while it has an app enabled for agents, however many apps that is, and an agent driving the browser itself uses 5 credits a minute. Credit packs stay valid for 12 months and stack, so unused credits carry over.

| Credits | Price, one time | Calls at 10 credits | Per 1,000 credits |
|---|---|---|---|
| 5,000 | $29 | 500 | $5.80 |
| 15,000 | $79 | 1,500 | $5.27 |
| 32,000 | $149 | 3,200 | $4.66 |
| 60,000 | $249 | 6,000 | $4.15 |

Only successful calls use credits; failed calls and timeouts cost nothing. At a balance of 0 calls pause, never a surprise charge. Authenticate with the `Authorization: Bearer` header. [See full pricing](https://cotlet.dev/pricing.md)

## How Cotlet holds your access

Cotlet hosts MCP servers and REST APIs for apps with no usable API. Your agent works in your own Recruiterflow account.

- **Company details:** Cotlet is run by Take Group sp. z o.o., a company registered in Poland. Its full address and registration numbers are in the Terms of service. [Terms of service](https://cotlet.dev/terms)
- **Your sign-in:** You sign in to Recruiterflow yourself, in your own Cloud Browser: a Chrome we run for you in the EU, one per app. We never save your password (password saving is off), the profile is stored encrypted with AES-256-GCM, and your agents get Recruiterflow only after you enable it. When Recruiterflow signs you out, your agent gives you a link to sign in again. [Security](https://cotlet.dev/security.md)
- **Revoking access:** Press Disable for agents next to Recruiterflow, sign out of Recruiterflow in your Cloud Browser, or reset the browser. Every background request is listed in your Background activity. Actions that reach other people wait for your OK unless you switch that off per tool.
- **What we never do:** Store passwords, solve CAPTCHAs or bypass MFA.
- **Recruiterflow's terms:** You use your own Recruiterflow account and stay responsible for following Recruiterflow's terms. Cotlet is independent and not affiliated with Recruiterflow. [Terms](https://cotlet.dev/terms)
- **Contact:** Questions about the company, security or an app: [contact@cotlet.dev](mailto:contact@cotlet.dev)

## Frequently asked questions

**How do I get access?**

Sign up free, open Recruiterflow in the console and press Request access. Then you create your API key and connect Recruiterflow there.

**Do I need to be technical?**

No. You sign in to Recruiterflow once in your Cloud Browser, a normal Chrome you open from the console, and paste one command into your agent, or one URL into n8n. Your agent can walk you through it. There is no server to install, update or fix.

**Is it safe to connect Recruiterflow to Cotlet?**

Yes. You sign in to Recruiterflow yourself, in your own Cloud Browser in the EU, and we never save your password. Your agents only get Recruiterflow once you enable it, every background request is listed, and the browser profile is stored encrypted with AES-256-GCM, the cipher 1Password uses for its vaults. The AI model never sees a login, posts and messages wait for your OK, and Disable for agents cuts access in one click. Independent scanners grade cotlet.dev A+ on Qualys SSL Labs, securityheaders.com and Mozilla Observatory; live results are on https://cotlet.dev/security.

**Is a hosted server safer than a local one? My Recruiterflow sign-in would leave my computer.**

On Cotlet you sign in inside your own Cloud Browser, which only you open, and its profile is stored encrypted with AES-256-GCM in the EU. Agents get only the apps you enable, and every background request is listed. A local server keeps your Recruiterflow cookie in a plain file on your computer, readable by any program you run, and stops when your computer is off.

**Why does Cotlet send requests instead of clicking in my browser?**

To be fast, Cotlet doesn't click through Recruiterflow's pages. It sends the same requests your browser would, from your browser's IP with its cookies, without opening a window. Recruiterflow sees the same browser and IP you signed in with, and every request is listed in your Background activity.

**What if someone gets my Cotlet API key?**

The key holds no Recruiterflow login or cookies, it only asks Cotlet to run a tool. It can call only the apps and tools you gave it, and a read-only key changes nothing. Anything that reaches other people, like posts, comments or messages, waits for your OK in the dashboard by default, so a leaked key cannot post or message as you. When you switch approval off for a scheduled job, give that job its own key limited to that one tool. Every call is in your activity log, and deleting the key ends access at once.

**Why a signed-in browser and not OAuth, like other integration platforms?**

Recruiterflow offers no OAuth token you can simply grant for these tools: its official API leaves them out or needs a developer app, a plan or an approval first (see the official API section above). That is why Cotlet sets the limits itself: per key, per tool, with your approval before anything reaches other people. Cotlet is run by Take Group sp. z o.o., an EU company (VAT PL6342984273).

**Do I need a Recruiterflow API key?**

No. Cotlet works in your own signed-in Recruiterflow account, with your role. Recruiterflow's own API keys are issued by its support team on request and are tied to a workspace; the help center does not say which plan includes them (Recruiterflow Help, checked 23 Oct 2026).

**Why does a stage move sometimes ask for more fields?**

An admin can make fields mandatory on a stage under Settings > Job Settings > Customize Stage Settings, a feature of the Advanced Plan and Custom Plan. A move into a Hired stage usually asks for placement details and a move into a Rejected stage asks for a disqualification reason. The tool returns these questions and moves nothing until they are answered.

**What does it not cover?**

Text only: nothing uploads files or CVs. Sequences, Recipes, scorecards, placements and revenue, job creation and deletes are not built, and Cotlet never changes your account settings, users or billing. Official Recruiterflow MCP and your normal login keep working next to it.

**Can my agent post or send messages in Recruiterflow without asking me?**

No. Every call to move_candidate_stage, disqualify_candidate, add_note, create_task or close_job waits for your OK by default. For scheduled automations you can switch confirmation off per tool in your dashboard, for example only for approvals. add_candidate and add_candidate_to_job run without asking, because they send nothing to anyone and one call undoes it.

**Can I use the Recruiterflow API in n8n?**

Yes. Add https://cotlet.dev/mcp/v1 with your API key in n8n's MCP Client node, or call its endpoints under https://cotlet.dev/api/v1/recruiterflow from the HTTP Request node.

---

Give your AI agents your signed-in browser.

**Product:** [Integrations](https://cotlet.dev/integrations.md) · [Use cases](https://cotlet.dev/use-cases.md) · [How it works](https://cotlet.dev/how-it-works.md) · [Pricing](https://cotlet.dev/pricing.md) · [Security](https://cotlet.dev/security.md)

**Resources:** [Blog](https://cotlet.dev/blog.md) · [API docs](https://cotlet.dev/docs.md) · [Help center](https://cotlet.dev/help.md) · [Changelog](https://cotlet.dev/changelog.md) · [GitHub](https://github.com/cotletdev/cotlet)

**Solutions:** [For developers](https://cotlet.dev/for-developers.md) · [For automation agencies](https://cotlet.dev/for-agencies.md)

**Company:** [About](https://cotlet.dev/about.md) · [AI info: company facts](https://cotlet.dev/ai-info.md) · [Contact](https://cotlet.dev/contact.md)

**Legal:** [Terms of service](https://cotlet.dev/terms) · [Privacy policy](https://cotlet.dev/privacy) · [Refund policy](https://cotlet.dev/refunds) · [Acceptable use](https://cotlet.dev/acceptable-use) · [Cookie policy](https://cotlet.dev/cookies) · [DPA](https://cotlet.dev/dpa) · [Subprocessors](https://cotlet.dev/subprocessors)

**Elsewhere:** [Status page](https://status.cotlet.dev) · [Cotlet on GitHub](https://github.com/cotletdev) · [Cotlet on X](https://x.com/cotletdev) · [Cotlet on LinkedIn](https://www.linkedin.com/company/cotletdev) · [Cotlet on Product Hunt](https://www.producthunt.com/products/cotlet) · [Cotlet on Crunchbase](https://www.crunchbase.com/organization/cotlet) · [Cotlet on SaaSHub](https://www.saashub.com/cotlet)

Cotlet.dev is built by Bart Krawczyk and Jake Slugocki, the founders of Take Group sp. z o.o., ul. Wincentego Janasa 4, 40-855 Katowice, Poland. KRS 0000871398, NIP 6342984273, VAT EU: PL6342984273. [About us](https://cotlet.dev/about.md)

Cotlet is an independent service. It is not affiliated with, endorsed by or sponsored by any of the products listed on this site. Product names are trademarks of their respective owners.
