Connect Ashby to ChatGPT: Manage Hiring Pipelines & Candidate Data
Learn how to connect Ashby to ChatGPT using a managed MCP server. Automate candidate sourcing, application updates, and interview scheduling without custom code.
You want to connect Ashby to ChatGPT so your AI agents can read candidate profiles, update application stages, and draft interview debriefs based on historical context (if you're looking to automate customer support instead, check out our guide on connecting Pylon to ChatGPT). Here is exactly how to do it using a Model Context Protocol (MCP) server.
Giving a Large Language Model (LLM) read and write access to your Ashby Applicant Tracking System (ATS) is an engineering challenge. You either spend weeks building, hosting, and maintaining a custom MCP server, or you use a managed infrastructure layer that handles the boilerplate for you. This guide breaks down exactly how to use Truto's SuperAI to generate a secure, managed MCP server for Ashby, connect it natively to ChatGPT, and execute complex recruiting workflows using natural language.
The Engineering Reality of Custom Ashby Connectors
A custom MCP server is a self-hosted integration layer that translates an LLM's tool calls into REST API requests.
While Anthropic's open standard provides a predictable way for models to discover tools, implementing it against vendor APIs is painful. If you decide to build a custom MCP server for Ashby, you are responsible for the entire API lifecycle.
Pagination and Sync Tokens
Ashby relies heavily on opaque cursors and syncToken logic for incremental synchronization. As we noted when connecting Kandji to ChatGPT, LLMs are notoriously bad at managing pagination state on their own. If you build a custom server, you must explicitly instruct the LLM to pass the nextCursor value back exactly as received. If the model modifies the cursor string, the pagination breaks. You also have to write the logic to handle the syncToken to ensure you only fetch records updated since the last API request.
Strict Schema Maintenance
Ashby's API requires strict adherence to its data types. When moving a candidate to a new stage, you cannot just pass a string - you need the exact interviewStageId. Maintaining massive JSON schemas for 30+ endpoints so the LLM knows exactly which parameters are required takes constant upkeep.
Rate Limits and 429 Errors
Ashby enforces rate limits per API key. While the limits are generous for standard usage, an AI agent summarizing hundreds of candidate notes can easily trigger a 429 Too Many Requests error (a challenge we also covered in our Zendesk integration guide). Your custom server must implement exponential backoff and retry logic, otherwise the LLM simply crashes mid-thought.
How SuperAI Solves This
Instead of forcing a unified data model, SuperAI exposes the raw Ashby API directly to the LLM, but makes it intelligent. Truto automatically injects the necessary semantic descriptions, parameters, and schemas required to turn a raw Ashby endpoint into a highly reliable MCP tool.
When you point ChatGPT at SuperAI, you outsource the integration boilerplate. We handle the pagination instructions, the schema generation, and the rate-limit retries.
Step-by-Step: Connecting Ashby to ChatGPT
Step 1: Obtain your Ashby API Key
Ashby uses Basic Authentication with an API key.
- Log into Ashby as an administrator.
- Navigate to Settings > API Keys.
- Generate a new API key. Ensure it has the necessary permission scopes for the workflows you want to automate (e.g.,
candidatesRead,candidatesWrite,jobsWrite).
Step 2: Connect the Ashby Account in Truto
Pass the API key into Truto to create an integrated account. Truto securely encrypts and stores the credential, associating it with a unique integrated_account_id.
Step 3: Generate the MCP Server
Truto allows you to generate a self-contained MCP server URL scoped to your specific Ashby account. You can do this via the Truto UI or the API.
Method 1: Via the Truto UI
- Navigate to the integrated account page for your Ashby connection.
- Click the MCP Servers tab.
- Click Create MCP Server.
- Select your desired configuration (e.g., restrict to read-only methods, or filter by specific tags).
- Copy the generated MCP server URL.
Method 2: Via the API You can programmatically generate the server by making a POST request to the Truto API. This is the preferred method if you are provisioning AI agents for your own customers.
curl -X POST https://api.truto.one/integrated-account/<integrated_account_id>/mcp \
-H "Authorization: Bearer <your_truto_api_token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Ashby Recruiting Agent",
"config": {
"methods":["read", "write"]
}
}'The API returns a secure URL containing a cryptographic token. This URL alone is enough to authenticate and serve tools to the LLM.
Step 4: Add the MCP Server to ChatGPT
- Open ChatGPT and navigate to Settings > Apps > Advanced settings.
- Enable Developer mode (requires a Plus, Pro, Team, or Enterprise account).
- Under MCP servers / Custom connectors, click Add new.
- Name the connector (e.g., "Ashby ATS").
- Paste the Truto MCP server URL.
- Click Save.
ChatGPT will immediately connect to the URL, execute the MCP handshake, and discover all available Ashby tools.
The Architecture
Here is exactly how the data flows when ChatGPT executes a tool call against Ashby.
sequenceDiagram
participant LLM as ChatGPT
participant MCP as Truto MCP Router
participant Proxy as Truto Proxy API
participant Ashby as Ashby API
LLM->>MCP: Call list_all_ashby_candidates (limit: 50)
Note over MCP: Validates token & extracts integrated account context
MCP->>Proxy: Route to Ashby candidate.list endpoint
Note over Proxy: Injects Ashby API Key & handles formatting
Proxy->>Ashby: POST /candidate.list
Ashby-->>Proxy: Returns candidate data + nextCursor
Proxy-->>MCP: Normalizes response
MCP-->>LLM: Returns JSON with explicit cursor instructionsFull Tool Inventory for Ashby
Once connected, ChatGPT has access to the following tools. We derive these dynamically from Ashby's API definitions. You can view the full list of available tools and their descriptions on the Ashby integration page.
Candidate Management
Candidates are the core entity representing an individual person applying for a job.
- ashby_candidates_tag: Add a tag to a candidate using
candidateIdandtagId. Returns candidate details including id and name. - ashby_candidates_anonymize: Anonymize a candidate by id. Requires
candidateId. This action cannot be reversed and requires high-level permissions. - update_a_ashby_candidate_by_id: Update an existing candidate by
candidateId. Returns updated candidate fields including id, name, andprimaryEmailAddress. - ashby_candidates_project: Add a candidate to a project. Requires
candidateIdandprojectId. Returns candidate details. - get_single_ashby_candidate_by_id: Get a single candidate by
externalMappingId. Returns candidate details including id, name, and email address. - list_all_ashby_candidates: List candidates in Ashby. Returns candidate id,
createdAt,updatedAt, name,primaryEmailAddress, andemailAddresses.
Application Tracking
Applications link a Candidate to a specific Job and track their progress through interview stages.
- ashby_applications_change_source: Change the source of an application in Ashby. Requires
applicationIdandsourceId. Returns updated application details. - ashby_applications_transfer: Transfer an application with
applicationIdto a different job withjobId,interviewPlanId, andinterviewStageId. - update_a_ashby_application_by_id: Update an application by id in Ashby. Requires
applicationId. Returns updated application fields including id, status, and candidate info. - create_a_ashby_application: Create an application by considering a candidate for a job in Ashby. Requires
candidateIdandjobId. - ashby_applications_change_stage: Change the stage of an application by
applicationIdandinterviewStageIdin Ashby. Returns updated application details. - get_single_ashby_application_by_id: Fetch application details by id in Ashby. Requires
applicationId. Returns id,createdAt,updatedAt, status, and candidate info. - list_all_ashby_applications: Get all applications in the organization in Ashby. Returns application id,
createdAt,updatedAt, status, and candidate details.
Job Requisitions
Jobs represent the open roles you are actively hiring for.
- update_a_ashby_job_by_id: Update an existing job in Ashby by
jobId. Returns updated job fields including id, title, status, andlocationId. - create_a_ashby_job: Create a new job in Ashby with required parameters title,
teamId, andlocationId. Returns job id, title, and status. - ashby_jobs_set_status: Set the status of a job by id in Ashby. Requires
jobIdand status. Returns updated job fields. - list_all_ashby_jobs: List all jobs in Ashby with optional filtering by status. Returns job id, title, status, and
employmentType. - get_single_ashby_job_by_id: Get information about a specific job in Ashby. Returns fields including id, title, status, and location.
Departments and Organization
Departments provide structural categorization for job listings.
- ashby_departments_restore: Restore a department by
departmentIdin Ashby. Returns the department's id, name,isArchivedstatus, andparentId. - delete_a_ashby_department_by_id: Archive a department by
departmentIdin Ashby. Returns the department's id, name, andisArchivedstatus. - ashby_departments_move: Move a department by
departmentIdto another parent usingparentIdin Ashby. Returns id, name, andisArchivedstatus. - update_a_ashby_department_by_id: Update a department using
departmentIdand name in Ashby. Returns id, name,isArchived, andparentId. - create_a_ashby_department: Create a department with name and optional
parentIdin Ashby. Returns id, name,isArchived, andparentId. - get_single_ashby_department_by_id: Fetch department details by id in Ashby. Requires
departmentId. Returns id, name,isArchived, andparentId. - list_all_ashby_departments: List all departments in Ashby. Returns id, name,
isArchived, andparentIdfields for each department.
Interviews and Offers
Manage the evaluation loop and final hiring outcomes.
- get_single_ashby_interview_by_id: Fetch interview details by id in Ashby. Requires id. Returns id, title,
isArchived,isDebrief, and instructions. - list_all_ashby_interviews: List all interviews in Ashby. Returns id, title,
isArchived,isDebrief, andinstructionsHtml. - get_single_ashby_offer_by_id: Get details about a single offer by id in Ashby. Requires offer id. Returns fields including id,
decidedAt, andapplicationId. - create_a_ashby_offer: Create a new offer with
offerProcessId,offerFormId, andofferFormcontainingfieldSubmissionsin Ashby. - update_a_ashby_offer_by_id: Update an existing offer by providing
offerIdandofferFormwithfieldSubmissionsin Ashby. - list_all_ashby_offers: Get a list of all offers with their latest version in Ashby. Returns id,
decidedAt, and status.
Users
Users represent the recruiters, hiring managers, and interviewers in the system.
- list_all_ashby_users: Get a list of all Ashby users. Returns id,
firstName,lastName, email, andglobalRole. - get_single_ashby_user_by_id: Get an Ashby user by id. Requires
userId. Returns id, name, email,globalRole, and enabled status.
Real-World ChatGPT Prompts for Recruiting Workflows
Once connected, you can execute complex, multi-step workflows using plain English. Because the LLM understands the schemas, it knows exactly which tools to chain together.
Scenario 1: Candidate Triage and Tagging
Prompt: "Find all active applications for the 'Senior Frontend Engineer' job. If the candidate applied more than 14 days ago and is still in the 'Initial Screen' stage, tag their candidate profile with 'Needs Review'."
Execution Flow:
- ChatGPT calls
list_all_ashby_jobsto find the ID for 'Senior Frontend Engineer'. - It calls
list_all_ashby_applicationsfiltering by the job ID. - It evaluates the
createdAttimestamps and current stage. - For matching records, it calls
ashby_candidates_tagusing the respectivecandidateId.
Scenario 2: Orchestrating an Offer
Prompt: "Draft an offer for John Doe for the Data Scientist role. Use the standard engineering offer form. Set the decision deadline to next Friday."
Execution Flow:
- ChatGPT calls
list_all_ashby_candidatessearching for "John Doe". - It calls
list_all_ashby_applicationsto find his active application for the Data Scientist role. - It calls
create_a_ashby_offerpassing theapplicationId, the correctofferFormId, and populating thefieldSubmissionswith the deadline date.
Scenario 3: Anonymizing Rejected Candidates (Compliance)
Prompt: "Find all candidates who were rejected more than 2 years ago and anonymize their records to comply with GDPR."
Execution Flow:
- ChatGPT calls
list_all_ashby_applicationsfiltering by the rejected status. - It checks the
updatedAttimestamp. - For applications older than 2 years, it extracts the
candidateId. - It calls
ashby_candidates_anonymizefor each ID.
The anonymize action is permanent. Always ensure your API key permissions are strictly scoped, and consider requiring a human-in-the-loop confirmation before allowing an AI agent to execute destructive actions.
Strategic Wrap-Up
Building AI agents that interact with your ATS is no longer an API integration problem. It is an orchestration problem.
By using an MCP server, you decouple the complexity of Ashby's API from your agent's core logic. You do not need to write code to handle cursor pagination, manage API keys, or keep JSON schemas up to date. You simply provide the LLM with the right tools and focus on designing the prompts that drive your hiring workflows.
FAQ
- How does the Truto MCP server handle Ashby's API rate limits?
- Truto's proxy layer automatically manages rate limits and 429 errors. It implements exponential backoff and retries, ensuring the LLM doesn't crash mid-execution when processing large volumes of candidate data.
- Can I restrict which Ashby endpoints the AI agent can access?
- Yes. When creating the MCP server in Truto, you can use method filtering (e.g., read-only) or tag filtering to strictly limit which tools are exposed to ChatGPT.
- Does the LLM handle Ashby's cursor pagination automatically?
- Yes. Truto injects explicit instructions into the tool schemas, telling the LLM exactly how to pass the nextCursor value back in subsequent requests without modifying it.