canonical: https://jentic.com/apis/bullhorn.github.io/bullhorn

# Bullhorn Resume Parsing API

Jentic publishes the only available OpenAPI specification for Bullhorn Resume Parsing API, keeping it validated and agent-ready. The Bullhorn Resume Parsing API converts uploaded CVs and resume documents into structured candidate records inside the Bullhorn ATS, then lets recruiting workflows build out the candidate's education history, work history, primary skills, and attached files. It is scoped to the candidate intake path: parse a resume, create the candidate entity, enrich it with related sub-entities, and attach the original document. The API is part of Bullhorn's broader staffing platform and uses Bullhorn's standard OAuth 2.0 authorization-code flow with a per-corporation REST base URL.

## For AI agents

Parse resume files into structured candidate data and create Bullhorn ATS candidates with education, work history, skills, and file attachments.

## Scope

Does not handle job postings, interview scheduling, or payroll - use for resume parsing and candidate creation in Bullhorn only.

## Capabilities

- Parse a PDF, DOC, or DOCX resume into a Bullhorn candidate record via /resume/parseToCandidate
- Create a new candidate entity in the Bullhorn ATS with PUT /entity/Candidate
- Attach education records to a candidate via /entity/CandidateEducation
- Attach work history records to a candidate via /entity/CandidateWorkHistory
- Add primary skills to a candidate by skill ID list
- Look up the available skill taxonomy via /options/Skill
- Upload the original resume file as a candidate attachment

## Use cases

### Automated resume intake

Convert inbound resume files (PDF, DOC, DOCX) into structured Bullhorn candidate records without manual data entry. The /resume/parseToCandidate endpoint extracts contact details, experience, and education in one call, then the candidate, work history, and education entities are persisted in the ATS. Suitable for high-volume staffing agencies processing hundreds of resumes per day.

Example prompt: Parse a resume PDF via POST /resume/parseToCandidate, create the returned candidate with PUT /entity/Candidate, then attach the original file with PUT /file/Candidate/{candidateId}/raw.

### Candidate enrichment after parsing

After a candidate is created from a parsed resume, attach structured education and work history sub-entities and assign primary skills from the Bullhorn taxonomy. This produces a fully populated candidate profile that recruiters can search by skill, school, or employer. Typical enrichment runs in under a minute per candidate when the resume contains complete history sections.

Example prompt: For candidate 12345, PUT /entity/CandidateEducation for each school, PUT /entity/CandidateWorkHistory for each role, and PUT /entity/Candidate/12345/primarySkills/{skillIds} with the matched skill IDs.

### Resume file management

Maintain a clean audit trail by storing the original resume document alongside the parsed candidate record. The file attachment endpoint accepts the raw binary, and the candidate files listing endpoint lets recruiters confirm what artifacts have been preserved. This satisfies common compliance and audit requirements in staffing operations.

Example prompt: Attach the source resume to candidate 12345 via PUT /file/Candidate/12345/raw, then GET /entityFiles/Candidate/12345 to confirm the file appears in the candidate's file list.

### AI agent recruiting assistant via Jentic

An AI recruiting assistant accepts an emailed resume, parses it, creates a Bullhorn candidate, and confirms the import to the recruiter - all without the agent handling raw OAuth tokens. Jentic stores the Bullhorn refresh token and issues scoped access for each call, so the agent only ever sees the structured response from each operation.

Example prompt: Search Jentic for 'parse a resume into Bullhorn', load the parseToCandidate operation schema, then execute it with the resume bytes and report the new candidate ID back to the recruiter.

## Key endpoints

| Method | Path | Description |
| --- | --- | --- |
| POST | /resume/parseToCandidate | Parse a resume document into candidate data |
| PUT | /entity/Candidate | Create a candidate entity |
| GET | /entity/Candidate/{candidateId} | Retrieve a candidate |
| PUT | /entity/CandidateEducation | Create a candidate education record |
| PUT | /entity/CandidateWorkHistory | Create a candidate work history record |
| PUT | /entity/Candidate/{candidateId}/primarySkills/{skillIds} | Add primary skills to a candidate |
| PUT | /file/Candidate/{candidateId}/raw | Attach a resume file to a candidate |
| GET | /entityFiles/Candidate/{candidateId} | List files attached to a candidate |

## Key resources

- **Resume** — Parse uploaded resume documents into structured candidate data.
- **Candidate** — Create and retrieve candidate entities in the Bullhorn ATS.
- **CandidateEducation** — Attach education history records to a candidate.
- **CandidateWorkHistory** — Attach work history records to a candidate.
- **Skills** — Look up the Bullhorn skill taxonomy and assign primary skills to a candidate.
- **Files** — Attach resume files to a candidate and list all candidate file attachments.

## Why Jentic

- **Setup:** Wiring Bullhorn resume parsing by hand means running its OAuth 2.0 flow, resolving the per-user corpToken into the rest-services base path, and keeping tokens refreshed yourself. Through Jentic you install once, import the Bullhorn Resume Parsing API from the API Directory, store the credentials once, and your agent calls it.
- **Permission scoping:** Bullhorn puts the candidate id in the URL path (/entity/Candidate/{candidateId}/...), so a rule can pin your agent to work on one candidate: it can parse a resume and attach education, work history, and skills for that candidate and nothing else. You choose the operations it may call, so it can parse and enrich candidates without being able to reach unrelated entities unless you add them.
- **Credential handling:** Your Bullhorn OAuth refresh token and corpToken are stored once, encrypted, by your own Jentic One instance, and only a scoped access token is injected at execution time. The long-lived secrets never enter the agent's prompt, logs, or context.
- **Discovery method:** Agents search Jentic by intent such as 'parse a resume into Bullhorn' or 'attach a candidate work history', and Jentic returns the matching Bullhorn operation with its input schema so the agent calls the right endpoint without browsing the reference docs.

## Related APIs

- **Bullhorn Resume Parsing (bullhornstaffing.com)** — Same Bullhorn resume parsing surface published under the bullhornstaffing.com vendor domain.
- **Greenhouse Harvest API** — Greenhouse's recruiting platform with a candidate and application API for ATS workflows.
- **Workable API** — Workable ATS API for jobs, candidates, and hiring stages.
- **Lever API** — Lever's recruiting API can sync candidates sourced elsewhere into a complementary pipeline.

## FAQ

### Why is there no official OpenAPI spec for Bullhorn Resume Parsing API?

Bullhorn does not publish an OpenAPI specification. Jentic generates and maintains this spec so that AI agents and developers can call Bullhorn Resume Parsing API via structured tooling. It is validated against the live API and kept up to date. Get started with Jentic One, the self-hosted execution layer.

### What authentication does the Bullhorn Resume Parsing API use?

It uses OAuth 2.0 authorization-code flow against https://auth.bullhornstaffing.com/oauth/authorize and /oauth/token. Each request also includes a per-corporation REST base URL that contains your corpToken. Through Jentic, refresh tokens stay in the vault and the agent only receives short-lived access tokens scoped to the call it is making.

### Can I parse a PDF resume directly with the Bullhorn Resume Parsing API?

Yes. POST /resume/parseToCandidate accepts the resume binary and returns a candidate object with parsed fields populated. You can then persist that object with PUT /entity/Candidate and attach the original file with PUT /file/Candidate/{candidateId}/raw.

### How do I add work history and education to a Bullhorn candidate after parsing?

Use PUT /entity/CandidateWorkHistory with the candidate ID and role data for each previous job, and PUT /entity/CandidateEducation for each school. These calls are independent and can be parallelised to speed up bulk imports.

### What are the rate limits for the Bullhorn Resume Parsing API?

The OpenAPI spec does not declare rate limits. Bullhorn enforces per-corporation REST throttles documented in the Bullhorn developer portal - design batch resume imports with retry on 429 responses and back off when the platform signals contention.

### How do I parse a resume with Bullhorn through Jentic?

Install the Jentic SDK with `pip install jentic`, then search for 'parse a resume into Bullhorn'. Jentic returns the parseToCandidate operation, you load its schema, and execute with the resume bytes - credentials are pulled from your Jentic One instance automatically.

### Can I limit what my agent is allowed to do with the Bullhorn Resume Parsing API?

Yes. Because you run Jentic One yourself, your own rules decide which Bullhorn operations and credentials the agent may use, so you can allow it to parse a resume with POST /resume/parseToCandidate and create a record with PUT /entity/Candidate while blocking everything else. Since Bullhorn puts the candidate id in the URL path, a rule can pin the agent to a single candidate and let it attach only that person's education, work history, and skills through /entity/CandidateEducation, /entity/CandidateWorkHistory, and the primarySkills path. It cannot reach unrelated entities or attach files unless you add those operations to its allowed set. The refresh token and corpToken stay with your instance, and only a scoped access token is injected when a permitted call runs.
