apply_to_job
ChatGPTApply to a job with one of the user's CVs. The listing's origin (from get_job) decides what happens: a team listing is DELIVERED into the owning workspace — email comes back null, there is nothing left for the user to send, and a contact_email passed for it is ignored. An external listing composes an application email (Gmail compose URL + markdown template) addressed to the listing's contact instead — nothing is sent; if it carries no contact_email, ask the user for the recipient and pass contact_email. IMPORTANT: applying PUBLISHES the chosen CV at a public share link anyone can open, and visits to it are tracked. Ask the user for explicit confirmation and pass confirm_publish=true only after they agreed.
classify_job_skill
ChatGPTSet how strongly a listing asks for a linked skill: required, optional or unspecified (not stated, or undo). skill_id from get_job's required_skills. Kept as a decision; later detection never replaces it. Weights matching; existing searches keep their scores (see basis_status).
create_cv
ChatGPTCreate a CV from a COMPLETE AptoraCV document; preserve all populated fields and entries. Call get_cv_schema and dry-run validate_cv first. Aliases normalize automatically; strict=true rejects entry loss. Unknown fields are rejected with a correction hint. PERSONAL workspace identity: firstName/lastName/name always become the signed-in account's name, discarding the submitted candidate name. Other data is preserved; normalized reports rule personal_workspace_identity. Import into a TEAM workspace to preserve someone else's name.
create_job
ChatGPTCreate a listing of this team workspace. Starts PRIVATE (off the board, no matching) until publish_job. Free on every team plan; skill detection only if the plan includes it.
delete_cv
ChatGPTDelete (soft-delete) a CV by id.
delete_job
ChatGPTDelete one of this workspace's job listings. Refused while candidates are still waiting on it — the refusal says how many; repeat the call with reject_open_applications=true to delete anyway.
get_capabilities
ChatGPTWhat this server can store: the supported AptoraCV sections, the section/field aliases it accepts, the allowed enum values and the supported import features (strict, merge, normalization). Call this before importing a resume from another format.
get_cv
ChatGPTFetch a single CV including its full resume data, plus profile_skills: the canonical skills detected on it, with the skill_id list_jobs filters by.
get_cv_schema
ChatGPTReturn the full AptoraCV resume JSON Schema that CV data must conform to. Prefer this over the aptora://cv-schema resource — it is a plain tool call and works on every client.
get_job
ChatGPTFetch one job listing including the full job spec, its required_skills (with the skill_id list_jobs filters by) and the application contact (contact_email/contact_person) when the listing carries one. For one listing the user singled out: a list_jobs result already opens each of its rows in place, so fetching a page row by row stacks up one card per job and says nothing the list did not. Listings of other workspaces are subject to a fair-use read budget of distinct listings per hour and day; re-reading one is free, and a refusal carries retry_after in seconds. Fair use is what the terms of service set out in § 17.
get_job_schema
ChatGPTThe field schema for creating/updating a job listing. Static — call it before the first write instead of guessing field names.
get_search
ChatGPTStatus and a page of results for a run started by search_candidates. 'status' is the search itself; 'refine_status' is the optional AI fit estimate and is null until refine_search is called. Results are complete and ranked either way — a failed estimate leaves them untouched. Paging costs no allowance.
list_applications
ChatGPTList the workspace's job applications, newest first, each with its composed application email — null for one delivered into a team workspace, whose status says where it stands instead. Readable in every workspace; whether NEW ones may be made is apply_to_job's question (a personal workspace or a consultancy team, never a company/agency team).
list_cvs
ChatGPTList all of the signed-in user's CVs (id, name, theme).
list_jobs
ChatGPTSearch jobs using an active job_title_id, esco_uri or at least 1 skill id. search_job_roles supplies selectable roles and ESCO concepts. ESCO includes descendants; role/ESCO and skill filters intersect. Skills match any selected id, ranked by overlap then recency; role-only uses recency. Skill IDs: get_cv profile_skills or listing required_skills. Summaries include skills; do not crawl rows with get_job, which is for a listing the user selected. Bare searches stop at page 10; ESCO keeps this cap even with extra filters. Pages and foreign listing details share account/workspace fair-use budgets across REST and MCP; refusals include retry_after seconds (§17).
list_searches
ChatGPTThis workspace's candidate searches, newest first, one page at a time.
list_shortlist
ChatGPTThe workspace shortlist, optionally filtered by job, one page at a time.
list_team_jobs
ChatGPTThe listings this workspace owns, including expired ones. Different from list_jobs, which is the public board.
publish_job
ChatGPTPut one of this workspace's listings on the public board and into candidate matching. Reversible with unpublish_job — the listing keeps its id, its skills and its match history either way.
refine_search
ChatGPTHave a model estimate how well the candidates a finished search found fit, from their careers: seniority against the role, how central the matching skills are to what someone actually does, whether the role plausibly interests them, and whether the missing skills are the kind one picks up. Re-ranks the SAME candidates — it never adds or removes anyone, and it never re-scores the counted overlap. Optional 'focus' is what matters beyond the listing ("must have worked in a regulated environment"). Costs one AI step from the workspace allowance; asking the same thing of the same run again is free. Poll get_search and read refine_status.
remove_from_shortlist
ChatGPTDrop one entry from the workspace shortlist.
search_candidates
ChatGPTFind candidates for a job (job_id) or for free criteria (filters) across every profile whose owner opted into being found. Ranks them by skill overlap and job-title fit and returns the evidence behind each score. Every search needs an anchor: a job_id (one of this workspace's listings, whose detected skills are the requirements) or at least 3 ids of active skills in the filters — those are what a candidate is ranked against. Every filter EXCLUDES on top of that: skills, titles, country, remote share and day rate each narrow the set, and no score buys a candidate back in. Within one list any entry counts, across lists all of them must. Skill ids come from a listing's required skills or a search result; an id that names no active skill is refused. This is DETERMINISTIC — it runs no model and forms no opinion beyond the counted overlap; call refine_search afterwards if you want that. Results never contain contact data — use send_outreach to reach someone. If the run comes back pending, poll get_search with the returned run_id. Runs and delivered profiles are subject to a fair-use read budget — fair use is what the terms of service set out in § 17 — and a refusal carries retry_after in seconds.
search_job_roles
ChatGPTFind roles and ESCO groups by German/English name or ISCO code. Use job_title_id or esco_uri with list_jobs; ESCO includes descendants.
send_outreach
ChatGPTSENDS A REAL MESSAGE TO A REAL PERSON, with optional email. One call, one recipient — no bulk parameter and there will not be one. The message is delivered by Aptora from our address; you never receive the candidate's address, and they can reply in Aptora if they want to or switch outreach off entirely. Each accepted message is metered against the workspace’s current plan allowance. Reuse an idempotency_key for retries of the same draft. Ask the user before calling this.
shortlist_candidate
ChatGPTSave a candidate to the workspace shortlist, optionally against a job. The shortlist belongs to the whole team.
unpublish_job
ChatGPTTake one of this workspace's listings back off the public board and out of candidate matching. The listing itself stays.
update_cv
ChatGPTUpdate a CV's name, data and/or theme. Only provided fields change. By default data REPLACES the stored document, so any section you omit is lost — pass merge=true to patch the stored CV instead (sections you send replace their counterpart, sections you omit are kept). The response reports received vs. stored counts per section. In a PERSONAL workspace the candidate name is always the signed-in account's — see create_cv.
update_job
ChatGPTUpdate a listing of this workspace; only named fields change, null clears one. Saving never re-detects skills: pass detect_skills=true after a spec change. stated_skills only adds.
validate_cv
ChatGPTDry-run: validate a AptoraCV resume document WITHOUT writing anything. Returns whether it is valid, any schema errors, the normalization it would apply, how many entries each section would store versus how many you sent, and any field that is not part of AptoraCV. Use this before create_cv/update_cv to confirm no data is lost. In a PERSONAL workspace the reported normalization includes the identity binding the write would apply, so this dry run and the write agree.
validate_job
ChatGPTDry-run a listing: what is missing or ignored; writes nothing. Use before create_job. Every plan; detect_skills needs one with skill detection.