Worlds / Hr and identity
Greenhouse API
A local Greenhouse with jobs, candidates, applications, interview stages, scorecards and offers. Test the recruiting agent that moves applications, rejects with the right reason and drafts offers for approval.
- Base path
/v1- Auth
- API key over HTTP basic auth (Harvest API), the world key
- Endpoints
- 14
- Status
- Active today
This reference previews the surface the Greenhouse world serves in the closed beta. Paths mirror the public Greenhouse API; the exact subset is confirmed when your workflow is scoped.
Connect
The run gives your agent these bindings. Keep your SDK; change only where it sends requests.
| binding | meaning |
|---|---|
WORLDS_GREENHOUSE_URL | This world's origin followed by /v1 |
WORLDS_API_KEY | The world key, accepted wherever Greenhouse expects a credential |
WORLDS_WORLD_ID | The isolated world's identity |
const base = process.env.WORLDS_GREENHOUSE_URL;
const auth = Buffer.from(process.env.WORLDS_API_KEY + ":").toString("base64");
const res = await fetch(base + "/v1/candidates?per_page=20", {
headers: { Authorization: "Basic " + auth },
});
const candidates = await res.json();API reference
Candidates
People in the hiring pipeline.
- GET
/v1/candidatesList candidates - POST
/v1/candidatesAdd a candidate - GET
/v1/candidates/{id}Get a candidate - PATCH
/v1/candidates/{id}Edit a candidate
Fields · 6
id | integer | Candidate id |
first_name | string | First name |
last_name | string | Last name |
email_addresses | array | Email addresses |
applications | array | Applications from this candidate |
tags | array | Tags |
Applications
A candidate's application to a job and where it stands.
- GET
/v1/applicationsList applications - GET
/v1/applications/{id}Get an application - POST
/v1/applications/{id}/advanceMove an application to the next stage - POST
/v1/applications/{id}/rejectReject an application
Fields · 5
id | integer | Application id |
candidate_id | integer | Candidate |
status | string | active, rejected or hired |
current_stage | object | Stage the application is in |
jobs | array | Jobs applied to |
Jobs
Open and closed roles.
- GET
/v1/jobsList jobs - GET
/v1/jobs/{id}Get a job - GET
/v1/jobs/{id}/stagesList a job's stages
Fields · 5
id | integer | Job id |
name | string | Job name |
status | string | open, closed or draft |
departments | array | Departments |
openings | array | Openings on the job |
Scorecards and interviews
Interview feedback left by the hiring team.
- GET
/v1/scorecardsList scorecards - GET
/v1/applications/{id}/scorecardsList scorecards for an application - GET
/v1/scheduled_interviewsList scheduled interviews
Fields · 5
id | integer | Scorecard id |
overall_recommendation | string | definitely_not through strong_yes |
interview | string | Interview name |
submitted_by | object | Interviewer |
submitted_at | datetime | Submission time |
Test workflow
- Prepare. Select the Greenhouse setup for your workflow and review its starting records, including candidates, applications, jobs.
- Connect. Configure your agent with this world's URL and key using the SDK example. Check that it reaches the intended API before running a test.
- Define. Describe the task, expected final changes and records that must stay untouched. Keep expected outcomes separate from the agent's instructions.
- Run and inspect. Use the dashboard or your workflow's generated CLI setup. Review final records and changes, then rerun from the same starting setup with the relevant failure conditions. Use Deployment and CI to automate the same workflow.
What to verify
- app 4410 moved to Onsite
- app 4392 moved to Offer
- app 4401 still in Onsite
- No rejections sent
- Lia Torres offer still pending approval
Test file
A task file names the jobs, the policy your agent is given and what the grader reads back from the world's final state. The agent never sees the expected outcomes.
# worlds/tasks.yaml · Greenhouse
version: 2
connector: greenhouse
seed: greenhouse-starter
mode: isolated
policy: >
Review the Senior Backend Engineer pipeline. Advance anyone whose scorecards
are all in and positive. Leave candidates with missing scorecards where they
are.
tasks:
- id: advance-applications-after-scorecards-are-in
prompt: Advance applications after scorecards are in
- id: reject-candidates-with-a-rejection-reason-and-email-template
prompt: Reject candidates with a rejection reason and email template
- id: create-an-offer-and-send-it-for-approval
prompt: Create an offer and send it for approval
expected:
- app 4410 moved to Onsite
- app 4392 moved to Offer
- app 4401 still in Onsite
- No rejections sent
- Lia Torres offer still pending approval
scenarios:
- rate-limited
- missing-user-header
- validation-errorSee Tasks and outcomes for every field, and Deployment and CI to run the file on every pull request.
Failure conditions
Each one fires before the handler, at the same step on every run.
| condition | what the agent sees |
|---|---|
rate-limited | Harvest returns 429 past the request window |
missing-user-header | Writes without On-Behalf-Of return 403 |
validation-error | A reject without a rejection_reason_id returns 422 |
webhook-twice | The candidate stage change webhook arrives two times |
Starting data
Start each run from the same records and relationships. The overview below describes the Greenhouse starter; use the setup supplied for your workflow when preparing your own snapshot.
| Records | Starting setup |
|---|---|
| jobs | 8 open jobs with hiring teams and interview plans |
| candidates | 150, some with applications to more than one job |
| applications | Spread across Application Review, Phone Screen, Onsite and Offer |
| scorecards | Submitted and missing scorecards with overall recommendations |
| offers | 3 offers, one waiting on approval |
The record shapes below reuse this world's API field definitions. They show illustrative values and placeholders, not an importable seed. API responses and seed input can differ; include all required records and references in the accepted import format for your workflow.
Candidates records
Candidates
People in the hiring pipeline.
| Field | Type | Meaning / relationship |
|---|---|---|
id | integer | Candidate id |
first_name | string | First name |
last_name | string | Last name |
email_addresses | array | Email addresses |
applications | array | Applications from this candidate |
tags | array | Tags |
{
"id": 1,
"first_name": "<First name>",
"last_name": "<Last name>",
"email_addresses": [],
"applications": [],
"tags": []
}Applications records
Applications
A candidate's application to a job and where it stands.
| Field | Type | Meaning / relationship |
|---|---|---|
id | integer | Application id |
candidate_id | integer | Candidate |
status | string | active, rejected or hired |
current_stage | object | Stage the application is in |
jobs | array | Jobs applied to |
{
"id": 1,
"candidate_id": 1,
"status": "<active, rejected or hired>",
"current_stage": {},
"jobs": []
}Jobs records
Jobs
Open and closed roles.
| Field | Type | Meaning / relationship |
|---|---|---|
id | integer | Job id |
name | string | Job name |
status | string | open, closed or draft |
departments | array | Departments |
openings | array | Openings on the job |
{
"id": 1,
"name": "<Job name>",
"status": "<open, closed or draft>",
"departments": [],
"openings": []
}Scorecards and interviews records
Scorecards and interviews
Interview feedback left by the hiring team.
| Field | Type | Meaning / relationship |
|---|---|---|
id | integer | Scorecard id |
overall_recommendation | string | definitely_not through strong_yes |
interview | string | Interview name |
submitted_by | object | Interviewer |
submitted_at | datetime | Submission time |
{
"id": 1,
"overall_recommendation": "<definitely_not through strong_yes>",
"interview": "<Interview name>",
"submitted_by": {},
"submitted_at": "<Submission time>"
}