{"openapi":"3.1.0","info":{"title":"JobFrog API","version":"1.0.0","description":"Versioned REST API for JobFrog. Authenticate with an API key (`Authorization: Bearer jf_...`, created under Settings → Developers); keys act as their owning staff user limited to their scopes. Same-origin calls from a signed-in staff browser session also work. Lists return `{ data, nextCursor }` (keyset pagination: pass `cursor`); single resources return `{ data }`; errors return `{ error: { code, message } }`. Rate limit: per key, fixed 60-second window, enforced per server instance (see X-RateLimit-* headers). The same operations are exposed as MCP tools at /api/mcp."},"servers":[{"url":"https://jobfrog.dev"},{"url":"https://www.jobfrog.dev"}],"tags":[{"name":"Candidates"},{"name":"Jobs"},{"name":"Pipeline"},{"name":"Market"},{"name":"Sources"},{"name":"Automations"},{"name":"Approvals"},{"name":"Sync"},{"name":"Assistant"},{"name":"Account"},{"name":"Public"}],"paths":{"/api/candidates":{"get":{"operationId":"listCandidates","tags":["Candidates"],"summary":"Search candidates","description":"Filter by free text (name, email, headline), status, origin, skills (any of), and identity status. Newest first.","security":[{"bearerAuth":["candidates:read"]},{"sessionCookie":[]}],"x-required-scope":"candidates:read","parameters":[{"name":"q","in":"query","required":false,"description":"Free text over name, email, and headline","schema":{"description":"Free text over name, email, and headline","type":"string","maxLength":200}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["new","active","passive","placed","unavailable","do_not_contact"]}},{"name":"origin","in":"query","required":false,"description":"How they entered the pool, e.g. \"recruiter\", \"jobdiva\", \"portal_signup\"","schema":{"description":"How they entered the pool, e.g. \"recruiter\", \"jobdiva\", \"portal_signup\"","type":"string","maxLength":50}},{"name":"skill","in":"query","required":false,"description":"Skill(s); matches candidates with any of them","schema":{"description":"Skill(s); matches candidates with any of them","anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"style":"form","explode":true},{"name":"identity","in":"query","required":false,"description":"Identity verification status","schema":{"description":"Identity verification status","type":"string","enum":["unverified","pending","verified","requires_input","failed"]}},{"name":"limit","in":"query","required":false,"description":"Page size (1-100, default 25)","schema":{"default":25,"description":"Page size (1-100, default 25)","type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from the previous page's nextCursor","schema":{"description":"Opaque cursor from the previous page's nextCursor","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"createCandidate","tags":["Candidates"],"summary":"Create a candidate","description":"Adds a candidate to the talent pool and starts matching. Email must be unique.","security":[{"bearerAuth":["candidates:write"]},{"sessionCookie":[]}],"x-required-scope":"candidates:write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":100},"lastName":{"type":"string","minLength":1,"maxLength":100},"email":{"type":"string","maxLength":320,"format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"phone":{"type":"string","maxLength":50},"headline":{"type":"string","maxLength":300},"location":{"type":"string","maxLength":200},"summary":{"type":"string","maxLength":4000},"linkedinUrl":{"type":"string","maxLength":500,"pattern":"^https?:\\/\\/"},"githubUrl":{"type":"string","maxLength":500,"pattern":"^https?:\\/\\/"},"skills":{"maxItems":60,"type":"array","items":{"type":"string","minLength":1,"maxLength":80}},"status":{"type":"string","enum":["new","active","passive","placed","unavailable","do_not_contact"]},"origin":{"description":"Defaults to \"recruiter\"","type":"string","minLength":1,"maxLength":50},"originDetail":{"type":"string","maxLength":300}},"required":["firstName","lastName"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/candidates/{id}":{"get":{"operationId":"getCandidate","tags":["Candidates"],"summary":"Get a candidate","description":"Full profile plus documents (with ATS reader scores), top matches, agency submissions, the candidate's own application tracker, and external ATS links.","security":[{"bearerAuth":["candidates:read"]},{"sessionCookie":[]}],"x-required-scope":"candidates:read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"patch":{"operationId":"updateCandidate","tags":["Candidates"],"summary":"Update a candidate profile","description":"Partial update; only fields present are changed. Staff callers may edit fields the operator locked against candidate edits; overrides are recorded on the event. Linked ATS records (e.g. JobDiva) receive the change via the sync outbox, and the candidate is re-matched.","security":[{"bearerAuth":["candidates:write"]},{"sessionCookie":[]}],"x-required-scope":"candidates:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":100},"lastName":{"type":"string","minLength":1,"maxLength":100},"email":{"anyOf":[{"type":"string","maxLength":320,"format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"null"}]},"phone":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}]},"location":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"headline":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}]},"summary":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"linkedinUrl":{"anyOf":[{"type":"string","maxLength":500,"pattern":"^https?:\\/\\/"},{"type":"null"}]},"githubUrl":{"anyOf":[{"type":"string","maxLength":500,"pattern":"^https?:\\/\\/"},{"type":"null"}]},"skills":{"description":"Replaces the full skill list","maxItems":60,"type":"array","items":{"type":"string","minLength":1,"maxLength":80}},"workAuthorization":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"workModePreference":{"anyOf":[{"type":"string","enum":["onsite","hybrid","remote"]},{"type":"null"}]},"desiredRateMin":{"description":"Minimum hourly rate","anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"desiredSalaryMin":{"description":"Minimum annual salary","anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"availableFrom":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}]},"status":{"type":"string","enum":["new","active","passive","placed","unavailable","do_not_contact"]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/candidates/{id}/notes":{"post":{"operationId":"addCandidateNote","tags":["Candidates"],"summary":"Add a note to a candidate","description":"Records the note on the candidate timeline and queues it for linked ATS records (e.g. a JobDiva candidate note).","security":[{"bearerAuth":["candidates:write"]},{"sessionCookie":[]}],"x-required-scope":"candidates:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","minLength":1,"maxLength":5000},"jobId":{"description":"Job the note relates to","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"action":{"description":"Activity type for the ATS, e.g. \"Call\", \"Email\", \"Screen\"","type":"string","maxLength":80}},"required":["note"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/candidates/{id}/refresh":{"post":{"operationId":"refreshCandidate","tags":["Candidates"],"summary":"Refresh a candidate","description":"Re-reads the candidate's latest resume, re-scores ATS readers, re-matches, and re-pulls from linked ATS records. JobFrog does not scrape LinkedIn; to refresh from LinkedIn, upload the candidate's LinkedIn 'Save to PDF' export. Work runs in the background; the response lists the queued jobs.","security":[{"bearerAuth":["candidates:write"]},{"sessionCookie":[]}],"x-required-scope":"candidates:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}}],"responses":{"202":{"description":"Accepted; work was queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/candidates/{id}/applications":{"get":{"operationId":"listApplications","tags":["Candidates"],"summary":"A candidate's application tracker","description":"Jobs the candidate is tracking or applied to on their own (our board, company sites, LinkedIn...). Agency submissions are in the pipeline endpoints.","security":[{"bearerAuth":["candidates:read"]},{"sessionCookie":[]}],"x-required-scope":"candidates:read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Candidate id"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["saved","applied","screening","interviewing","offer","hired","rejected","withdrawn"]}},{"name":"limit","in":"query","required":false,"description":"Page size (1-100, default 25)","schema":{"default":25,"description":"Page size (1-100, default 25)","type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from the previous page's nextCursor","schema":{"description":"Opaque cursor from the previous page's nextCursor","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/requisitions":{"get":{"operationId":"listJobs","tags":["Jobs"],"summary":"List requisitions and market postings","description":"Agency requisitions (kind \"requisition\", jobs we recruit for) and ingested market postings (kind \"market\", job-board signal). Includes internal fields such as bill/pay rates. Newest first.","security":[{"bearerAuth":["jobs:read"]},{"sessionCookie":[]}],"x-required-scope":"jobs:read","parameters":[{"name":"kind","in":"query","required":false,"description":"\"requisition\" (default): jobs we recruit for; \"market\": ingested postings; \"all\"","schema":{"default":"requisition","description":"\"requisition\" (default): jobs we recruit for; \"market\": ingested postings; \"all\"","type":"string","enum":["requisition","market","all"]}},{"name":"q","in":"query","required":false,"description":"Full-text search over title and description","schema":{"description":"Full-text search over title and description","type":"string","maxLength":200}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["draft","open","on_hold","filled","closed","cancelled"]}},{"name":"company","in":"query","required":false,"description":"Company name (partial) or exact domain","schema":{"description":"Company name (partial) or exact domain","type":"string","maxLength":200}},{"name":"skill","in":"query","required":false,"description":"Skill(s); matches jobs with any of them","schema":{"description":"Skill(s); matches jobs with any of them","anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"style":"form","explode":true},{"name":"mode","in":"query","required":false,"schema":{"type":"string","enum":["onsite","hybrid","remote"]}},{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["contract","contract_to_hire","direct_hire","temp"]}},{"name":"seniority","in":"query","required":false,"schema":{"type":"string","enum":["intern","junior","mid","senior","staff","principal","executive"]}},{"name":"location","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"limit","in":"query","required":false,"description":"Page size (1-100, default 25)","schema":{"default":25,"description":"Page size (1-100, default 25)","type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from the previous page's nextCursor","schema":{"description":"Opaque cursor from the previous page's nextCursor","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"createRequisition","tags":["Jobs"],"summary":"Open a requisition","description":"Creates an open agency requisition for a client (the company is created or promoted to active client) and starts matching candidates against it.","security":[{"bearerAuth":["jobs:write"]},{"sessionCookie":[]}],"x-required-scope":"jobs:write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"companyName":{"type":"string","minLength":1,"maxLength":200},"title":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":20000},"location":{"type":"string","maxLength":200},"workMode":{"type":"string","enum":["onsite","hybrid","remote"]},"employmentType":{"default":"direct_hire","type":"string","enum":["contract","contract_to_hire","direct_hire","temp"]},"skills":{"default":[],"maxItems":60,"type":"array","items":{"type":"string","minLength":1,"maxLength":80}},"mustHave":{"default":[],"description":"Must-have skills (also added to skills)","maxItems":30,"type":"array","items":{"type":"string","minLength":1,"maxLength":80}},"niceToHave":{"maxItems":30,"type":"array","items":{"type":"string","minLength":1,"maxLength":80}},"billRateMin":{"type":"number","minimum":0},"billRateMax":{"type":"number","minimum":0},"payRateMin":{"type":"number","minimum":0},"payRateMax":{"type":"number","minimum":0},"salaryMin":{"type":"number","minimum":0},"salaryMax":{"type":"number","minimum":0},"currency":{"default":"USD","type":"string","minLength":3,"maxLength":3},"priority":{"default":3,"type":"integer","minimum":1,"maximum":5},"openings":{"default":1,"type":"integer","minimum":1,"maximum":500},"isPublic":{"default":false,"description":"Show on your organization's careers page (and on the JobFrog network board and public API, obfuscated, if your organization lists roles there)","type":"boolean"}},"required":["companyName","title"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/requisitions/{id}":{"get":{"operationId":"getJob","tags":["Jobs"],"summary":"Get a job","description":"A requisition or market posting with its company, match count, and submission counts by stage.","security":[{"bearerAuth":["jobs:read"]},{"sessionCookie":[]}],"x-required-scope":"jobs:read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/requisitions/{id}/candidates":{"get":{"operationId":"rankCandidates","tags":["Jobs"],"summary":"Ranked candidates for a job","description":"Candidates ranked by match score for a job, with strengths/gaps and pipeline stage if already submitted. Uses stored matches; if the job has never been matched, scores active candidates live with the deterministic rule score (source \"live\").","security":[{"bearerAuth":["jobs:read"]},{"sessionCookie":[]}],"x-required-scope":"jobs:read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}},{"name":"limit","in":"query","required":false,"schema":{"default":20,"type":"integer","minimum":1,"maximum":100}},{"name":"minScore","in":"query","required":false,"schema":{"type":"number","minimum":0,"maximum":100}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/requisitions/{id}/match":{"post":{"operationId":"matchJob","tags":["Jobs"],"summary":"Re-match candidates to a job","description":"Queues the deterministic matcher for this job. Results appear in the job's ranked candidates.","security":[{"bearerAuth":["automations:run"]},{"sessionCookie":[]}],"x-required-scope":"automations:run","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}}],"responses":{"202":{"description":"Accepted; work was queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/companies":{"get":{"operationId":"listCompanies","tags":["Companies"],"summary":"List client companies","description":"Clients, prospects and inactive accounts in this workspace with open requisition and active placement counts. Newest first.","security":[{"bearerAuth":["jobs:read"]},{"sessionCookie":[]}],"x-required-scope":"jobs:read","parameters":[{"name":"q","in":"query","required":false,"description":"Name, industry or domain (partial)","schema":{"description":"Name, industry or domain (partial)","type":"string","maxLength":200}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["prospect","active_client","inactive","do_not_contact","market"]}},{"name":"limit","in":"query","required":false,"description":"Page size (1-100, default 25)","schema":{"default":25,"description":"Page size (1-100, default 25)","type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from the previous page's nextCursor","schema":{"description":"Opaque cursor from the previous page's nextCursor","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/companies/{id}":{"get":{"operationId":"getCompany","tags":["Companies"],"summary":"Get a client company","description":"One client account with commercial terms, contacts, requisition counts by status, submissions by stage, placements by status, and open receivables.","security":[{"bearerAuth":["jobs:read"]},{"sessionCookie":[]}],"x-required-scope":"jobs:read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"patch":{"operationId":"updateCompany","tags":["Companies"],"summary":"Update a client company","description":"Partial update of a client account: profile, relationship status, account owner, and commercial terms (markup, fee, payment terms, VMS). Only fields present change. Linked ATS company records get the change via the sync outbox when that ATS accepts company writes.","security":[{"bearerAuth":["jobs:write"]},{"sessionCookie":[]}],"x-required-scope":"jobs:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"domain":{"anyOf":[{"type":"string","maxLength":253},{"type":"null"}]},"industry":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"sizeBand":{"description":"Headcount band, e.g. \"1-10\", \"51-200\", \"10k+\"","anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"hqLocation":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"careersUrl":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"status":{"description":"Relationship status (market is reserved for ingested companies)","type":"string","enum":["prospect","active_client","inactive","do_not_contact"]},"ownerId":{"description":"Account owner: a recruiter or admin in this workspace, or null","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"defaultMarkupPercent":{"description":"Default markup on pay for contract roles, e.g. 45","anyOf":[{"type":"number","minimum":0,"maximum":500},{"type":"null"}]},"defaultFeePercent":{"description":"Default direct-hire placement fee, e.g. 20","anyOf":[{"type":"number","minimum":0,"maximum":100},{"type":"null"}]},"paymentTermsDays":{"description":"Net payment terms in days","anyOf":[{"type":"integer","minimum":0,"maximum":365},{"type":"null"}]},"vmsName":{"description":"Vendor management system the client routes reqs through, e.g. Beeline","anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"notes":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/companies/{id}/contacts":{"post":{"operationId":"createContact","tags":["Companies"],"summary":"Add a client contact","description":"Adds a person at a client company (hiring manager, talent acquisition, procurement, ...).","security":[{"bearerAuth":["jobs:write"]},{"sessionCookie":[]}],"x-required-scope":"jobs:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Company id (UUID)"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":100},"lastName":{"type":"string","minLength":1,"maxLength":100},"title":{"anyOf":[{"type":"string","maxLength":150},{"type":"null"}]},"role":{"default":"other","type":"string","enum":["hiring_manager","talent_acquisition","hr","procurement","executive","other"]},"email":{"anyOf":[{"type":"string","maxLength":254},{"type":"null"}]},"phone":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"linkedinUrl":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"doNotContact":{"type":"boolean"}},"required":["firstName","lastName"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/contacts/{id}":{"patch":{"operationId":"updateContact","tags":["Companies"],"summary":"Update a client contact","description":"Partial update; only fields present change.","security":[{"bearerAuth":["jobs:write"]},{"sessionCookie":[]}],"x-required-scope":"jobs:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":100},"lastName":{"type":"string","minLength":1,"maxLength":100},"title":{"anyOf":[{"type":"string","maxLength":150},{"type":"null"}]},"role":{"default":"other","type":"string","enum":["hiring_manager","talent_acquisition","hr","procurement","executive","other"]},"email":{"anyOf":[{"type":"string","maxLength":254},{"type":"null"}]},"phone":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"linkedinUrl":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"doNotContact":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"delete":{"operationId":"deleteContact","tags":["Companies"],"summary":"Remove a client contact","description":"Deletes the contact. Requisitions that named them as hiring contact keep working without one.","security":[{"bearerAuth":["jobs:write"]},{"sessionCookie":[]}],"x-required-scope":"jobs:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/pipeline":{"get":{"operationId":"listSubmissions","tags":["Pipeline"],"summary":"List pipeline submissions","description":"Agency submissions (candidate x requisition) filtered by stage(s), job, or candidate. Newest first.","security":[{"bearerAuth":["pipeline:read"]},{"sessionCookie":[]}],"x-required-scope":"pipeline:read","parameters":[{"name":"stage","in":"query","required":false,"description":"Stage(s): sourced, contacted, screening, shortlisted, submitted, client_review, interviewing, offer, placed, rejected, withdrawn","schema":{"description":"Stage(s): sourced, contacted, screening, shortlisted, submitted, client_review, interviewing, offer, placed, rejected, withdrawn","anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"style":"form","explode":true},{"name":"jobId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"candidateId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"limit","in":"query","required":false,"description":"Page size (1-100, default 25)","schema":{"default":25,"description":"Page size (1-100, default 25)","type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from the previous page's nextCursor","schema":{"description":"Opaque cursor from the previous page's nextCursor","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/pipeline/summary":{"get":{"operationId":"getPipelineSummary","tags":["Pipeline"],"summary":"Pipeline overview","description":"Submission counts by stage (optionally for one job) and the most recently moved submissions.","security":[{"bearerAuth":["pipeline:read"]},{"sessionCookie":[]}],"x-required-scope":"pipeline:read","parameters":[{"name":"jobId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"recent","in":"query","required":false,"description":"How many recently moved submissions to include","schema":{"default":15,"description":"How many recently moved submissions to include","type":"integer","minimum":0,"maximum":50}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/submissions/{id}":{"patch":{"operationId":"moveSubmissionStage","tags":["Pipeline"],"summary":"Move a submission to another stage","description":"Updates the stage (and stage timestamp), records a timeline event, and queues the write-back for linked ATS records (submittal status, or a new submittal once it reaches submitted).","security":[{"bearerAuth":["pipeline:write"]},{"sessionCookie":[]}],"x-required-scope":"pipeline:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"stage":{"type":"string","enum":["sourced","contacted","screening","shortlisted","submitted","client_review","interviewing","offer","placed","rejected","withdrawn"]},"reason":{"description":"Rejection/withdrawal reason (stored when stage is rejected or withdrawn)","type":"string","maxLength":1000}},"required":["stage"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/market/benchmarks":{"get":{"operationId":"listBenchmarks","tags":["Market"],"summary":"Compensation benchmarks","description":"Percentile pay (p10-p90) by normalized title, seniority, location, and employment type, computed from ingested postings. Hourly for contract/C2H/temp, annual for direct hire. Largest samples first.","security":[{"bearerAuth":["market:read"]},{"sessionCookie":[]}],"x-required-scope":"market:read","parameters":[{"name":"title","in":"query","required":false,"description":"Job title; normalized to a role family (e.g. \"Sr. Data Engineer\" -> \"data engineer\")","schema":{"description":"Job title; normalized to a role family (e.g. \"Sr. Data Engineer\" -> \"data engineer\")","type":"string","maxLength":200}},{"name":"seniority","in":"query","required":false,"schema":{"type":"string","enum":["intern","junior","mid","senior","staff","principal","executive"]}},{"name":"location","in":"query","required":false,"description":"\"US\", \"US-Remote\", or a metro/state label (partial match)","schema":{"description":"\"US\", \"US-Remote\", or a metro/state label (partial match)","type":"string","maxLength":200}},{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["contract","contract_to_hire","direct_hire","temp"]}},{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/market/benchmarks/recompute":{"post":{"operationId":"triggerBenchmarks","tags":["Market"],"summary":"Recompute benchmarks","description":"Queues a deterministic recompute of compensation percentiles from ingested postings.","security":[{"bearerAuth":["automations:run"]},{"sessionCookie":[]}],"x-required-scope":"automations:run","parameters":[],"responses":{"202":{"description":"Accepted; work was queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/market/reports":{"get":{"operationId":"listReports","tags":["Market"],"summary":"Market reports","description":"Narrative market analyses generated by the market agent, newest first.","security":[{"bearerAuth":["market:read"]},{"sessionCookie":[]}],"x-required-scope":"market:read","parameters":[{"name":"limit","in":"query","required":false,"description":"Page size (1-100, default 25)","schema":{"default":10,"description":"Page size (1-100, default 25)","type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from the previous page's nextCursor","schema":{"description":"Opaque cursor from the previous page's nextCursor","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"triggerReport","tags":["Market"],"summary":"Generate a market report","description":"Queues the market agent to write a narrative report (LLM-backed, runs in the background as an agent session).","security":[{"bearerAuth":["automations:run"]},{"sessionCookie":[]}],"x-required-scope":"automations:run","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"titles":{"maxItems":20,"type":"array","items":{"type":"string","minLength":1,"maxLength":200}},"locations":{"maxItems":20,"type":"array","items":{"type":"string","minLength":1,"maxLength":200}}}}}}},"responses":{"202":{"description":"Accepted; work was queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/sources":{"get":{"operationId":"listSources","tags":["Sources"],"summary":"List job sources","description":"Configured ingestion sources (public ATS boards, aggregator feeds, imports...) with last sync stats, errors, and board health (healthy, pending, empty, failing, cooling, paused, needs_config).","security":[{"bearerAuth":["jobs:read"]},{"sessionCookie":[]}],"x-required-scope":"jobs:read","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"createSource","tags":["Sources"],"summary":"Add a job board source","description":"Adds a public Greenhouse, Lever, or Ashby job board and queues its first sync.","security":[{"bearerAuth":["automations:run"]},{"sessionCookie":[]}],"x-required-scope":"automations:run","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","enum":["greenhouse","lever","ashby"]},"board":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[a-zA-Z0-9._-]+$"},"companyName":{"type":"string","minLength":1,"maxLength":200},"domain":{"type":"string","maxLength":200}},"required":["kind","board","companyName"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/sources/boards":{"post":{"operationId":"addBoard","tags":["Sources"],"summary":"Add a public job board (validated)","description":"Adds any supported public job board (Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable, Recruitee, BambooHR, ... or an aggregator feed) to the shared market catalog. The board is fetched once through its connector first: boards that fail or return no postings are rejected, and a board whose platform name doesn't match companyName is rejected unless force is set. Pass dryRun to only validate. On success the first sync is queued.","security":[{"bearerAuth":["automations:run"]},{"sessionCookie":[]}],"x-required-scope":"automations:run","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"platform":{"type":"string","enum":["greenhouse","lever","ashby","workday","smartrecruiters","workable","recruitee","personio","bamboohr","breezy","jobvite","jazzhr","teamtailor","pinpoint","rippling","remoteok","remotive","arbeitnow","themuse","usajobs","himalayas","jobicy","hackernews"],"description":"Connector platform, e.g. greenhouse, workday, himalayas"},"board":{"type":"string","minLength":1,"maxLength":300,"description":"Board token from the careers URL (Workday: \"{tenant}.wd{N}/{site}\"; aggregators: \"all\" or a filter)"},"companyName":{"description":"Employer name (required for single-company boards)","type":"string","minLength":1,"maxLength":200},"domain":{"description":"Employer domain, e.g. acme.com","type":"string","maxLength":200},"maxPages":{"type":"integer","minimum":1,"maximum":50},"maxDetails":{"type":"integer","minimum":0,"maximum":1000},"dryRun":{"default":false,"description":"Validate only; don't save","type":"boolean"},"force":{"default":false,"description":"Save even if the board's name doesn't match companyName","type":"boolean"}},"required":["platform","board"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/sources/sync":{"post":{"operationId":"syncAllSources","tags":["Sources"],"summary":"Sync all sources","description":"Queues ingestion for every enabled source.","security":[{"bearerAuth":["automations:run"]},{"sessionCookie":[]}],"x-required-scope":"automations:run","parameters":[],"responses":{"202":{"description":"Accepted; work was queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/sources/{id}/resume":{"post":{"operationId":"resumeSource","tags":["Sources"],"summary":"Resume a paused source","description":"Re-enables a source (e.g. one auto-paused after repeated failed syncs), clears its failure streak, and queues a sync.","security":[{"bearerAuth":["automations:run"]},{"sessionCookie":[]}],"x-required-scope":"automations:run","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/sources/{id}/sync":{"post":{"operationId":"syncSource","tags":["Sources"],"summary":"Sync one source","description":"Queues ingestion for one source.","security":[{"bearerAuth":["automations:run"]},{"sessionCookie":[]}],"x-required-scope":"automations:run","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}}],"responses":{"202":{"description":"Accepted; work was queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/automations":{"get":{"operationId":"listAutomationRuns","tags":["Automations"],"summary":"Recent automation runs","description":"Background job executions (queue or cron), newest first, with status, stats, and summary. Omits the step log; fetch one run for it.","security":[{"bearerAuth":["automations:run"]},{"sessionCookie":[]}],"x-required-scope":"automations:run","parameters":[{"name":"queue","in":"query","required":false,"schema":{"type":"string","maxLength":60}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["running","succeeded","failed","skipped"]}},{"name":"limit","in":"query","required":false,"description":"Page size (1-100, default 25)","schema":{"default":25,"description":"Page size (1-100, default 25)","type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from the previous page's nextCursor","schema":{"description":"Opaque cursor from the previous page's nextCursor","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/automations/runs/{id}":{"get":{"operationId":"getAutomationRun","tags":["Automations"],"summary":"Get an automation run","description":"One background job execution including its step log.","security":[{"bearerAuth":["automations:run"]},{"sessionCookie":[]}],"x-required-scope":"automations:run","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/automations/{queue}":{"post":{"operationId":"runAutomation","tags":["Automations"],"summary":"Trigger a background job (body is the queue payload)","description":"Queues one allowlisted background job with a validated payload. resume.parse: { documentId } re-parse a resume, then re-score and re-match; resume.score: { documentId, readers?, jobId? } score a resume with ATS readers; resume.variants: { documentId, jobId? } generate ATS-ready resume variants (LLM); match.job: { jobId } rule-match candidates to a job; match.candidate: { candidateId } rule-match a candidate to open jobs; source.sync: { sourceId } ingest one job source; source.sync_all: {} ingest all enabled sources; market.benchmarks: {} recompute comp benchmarks; market.report: { titles?, locations? } write a market report (LLM); ats.pull: { system } pull changes from an ATS (e.g. jobdiva); ats.push: { system? } flush the ATS write outbox; gmail.sync: { userId } sync one connected mailbox; gmail.sync_all: {} sync every connected mailbox.","security":[{"bearerAuth":["automations:run"]},{"sessionCookie":[]}],"x-required-scope":"automations:run","parameters":[{"name":"queue","in":"path","required":true,"schema":{"type":"string","enum":["resume.parse","resume.score","resume.variants","match.job","match.candidate","source.sync","source.sync_all","market.benchmarks","market.report","ats.pull","ats.push","gmail.sync","gmail.sync_all"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Queue payload; see the operation description for each queue's fields."}}}},"responses":{"202":{"description":"Accepted; work was queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/approvals":{"get":{"operationId":"listApprovals","tags":["Approvals"],"summary":"List approvals","description":"Agent actions waiting for a human (default) or in another status, newest first. The payload is exactly what will execute on approval.","security":[{"bearerAuth":["approvals:read"]},{"sessionCookie":[]}],"x-required-scope":"approvals:read","parameters":[{"name":"status","in":"query","required":false,"schema":{"default":"pending","type":"string","enum":["pending","approved","rejected","expired","auto_approved","executed","failed"]}},{"name":"actionType","in":"query","required":false,"schema":{"type":"string","maxLength":100}},{"name":"limit","in":"query","required":false,"description":"Page size (1-100, default 25)","schema":{"default":25,"description":"Page size (1-100, default 25)","type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from the previous page's nextCursor","schema":{"description":"Opaque cursor from the previous page's nextCursor","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/approvals/{id}":{"get":{"operationId":"getApproval","tags":["Approvals"],"summary":"Get an approval","security":[{"bearerAuth":["approvals:read"]},{"sessionCookie":[]}],"x-required-scope":"approvals:read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/approvals/{id}/decision":{"post":{"operationId":"decideApproval","tags":["Approvals"],"summary":"Approve or reject an agent action","description":"Decide a pending approval. On approve you may pass an edited payload; exactly that payload executes (queued as approval.execute). Rejecting cancels the agent run that proposed it. Fails with 409 if already decided.","security":[{"bearerAuth":["approvals:write"]},{"sessionCookie":[]}],"x-required-scope":"approvals:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Resource id (UUID)"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"decision":{"type":"string","enum":["approve","reject"]},"payload":{"description":"Edited action payload (approve only); replaces the proposed payload","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"note":{"type":"string","maxLength":2000}},"required":["decision"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/sync/{system}/pull":{"post":{"operationId":"triggerAtsSync","tags":["Sync"],"summary":"Pull from an ATS","description":"Queues an incremental pull from an external ATS (candidates, jobs, submittals; fills gaps, never overwrites JobFrog data or locked fields) or a push that flushes pending outbox writes to it. Runs in the sandbox when the ATS has no credentials configured.","security":[{"bearerAuth":["sync:run"]},{"sessionCookie":[]}],"x-required-scope":"sync:run","parameters":[{"name":"system","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":50,"description":"ATS id, e.g. \"jobdiva\""}}],"responses":{"202":{"description":"Accepted; work was queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/sync/{system}/push":{"post":{"operationId":"triggerAtsSync_push","tags":["Sync"],"summary":"Flush the outbox to an ATS","description":"Queues an incremental pull from an external ATS (candidates, jobs, submittals; fills gaps, never overwrites JobFrog data or locked fields) or a push that flushes pending outbox writes to it. Runs in the sandbox when the ATS has no credentials configured.","security":[{"bearerAuth":["sync:run"]},{"sessionCookie":[]}],"x-required-scope":"sync:run","parameters":[{"name":"system","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":50,"description":"ATS id, e.g. \"jobdiva\""}}],"responses":{"202":{"description":"Accepted; work was queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/sync/outbox":{"get":{"operationId":"listOutbox","tags":["Sync"],"summary":"ATS write outbox","description":"Writes JobFrog owes external systems (candidate updates, notes, resumes, submittals), newest first.","security":[{"bearerAuth":["sync:run"]},{"sessionCookie":[]}],"x-required-scope":"sync:run","parameters":[{"name":"system","in":"query","required":false,"schema":{"type":"string","maxLength":50}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","sending","sent","failed","skipped"]}},{"name":"limit","in":"query","required":false,"description":"Page size (1-100, default 25)","schema":{"default":25,"description":"Page size (1-100, default 25)","type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from the previous page's nextCursor","schema":{"description":"Opaque cursor from the previous page's nextCursor","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/sync/runs":{"get":{"operationId":"listSyncRuns","tags":["Sync"],"summary":"ATS sync runs","description":"Inbound/outbound sync executions with counts, newest first.","security":[{"bearerAuth":["sync:run"]},{"sessionCookie":[]}],"x-required-scope":"sync:run","parameters":[{"name":"system","in":"query","required":false,"schema":{"type":"string","maxLength":50}},{"name":"limit","in":"query","required":false,"description":"Page size (1-100, default 25)","schema":{"default":25,"description":"Page size (1-100, default 25)","type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from the previous page's nextCursor","schema":{"description":"Opaque cursor from the previous page's nextCursor","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/ask":{"post":{"operationId":"ask","tags":["Assistant"],"summary":"Ask JobFrog","description":"Answer a question about your workspace data (candidates, jobs, pipeline, market, agents) with the JobFrog assistant. Uses an LLM and read-only SQL; may start background tasks it mentions. Pass conversationId to continue a conversation.","security":[{"bearerAuth":["assistant:ask"]},{"sessionCookie":[]}],"x-required-scope":"assistant:ask","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":4000},"conversationId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["question"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/me":{"get":{"operationId":"getMe","tags":["Account"],"summary":"The acting user, auth method, and available scopes","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemEnvelope"}}}},"401":{"$ref":"#/components/responses/Error"}}}},"/api/jobs":{"get":{"operationId":"listPublicJobs","tags":["Public"],"summary":"Public job board search (keyless)","description":"Open, public market postings, plus recruiter-backed roles from organizations that list them on the JobFrog network (recruiterBacked: true; the client is always shown as \"Confidential client\"). Stable allowlisted shape. Filters: q, mode, type, seniority, skill, company (market postings only), location, cursor, limit.","security":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEnvelope"}}}}}}},"/api/jobs/{id}":{"get":{"operationId":"getPublicJob","tags":["Public"],"summary":"One public job posting (keyless)","security":[],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"jf_<env>_<random>","description":"API key. Scopes: candidates:read (Search candidates, profiles, documents, matches, application trackers); candidates:write (Create and edit candidates, add notes, refresh from resume/ATS); jobs:read (Requisitions, market postings, ranked candidates, client companies, sources); jobs:write (Open requisitions, edit client companies and contacts); pipeline:read (Submissions by stage and job); pipeline:write (Move submissions between stages); market:read (Comp benchmarks and market reports); approvals:read (Pending agent actions); approvals:write (Approve or reject agent actions); automations:run (Trigger allowlisted background jobs and read their runs); sync:run (Trigger ATS pull/push and read the sync outbox); assistant:ask (Ask JobFrog questions (the only LLM-backed operation))"},"sessionCookie":{"type":"apiKey","in":"cookie","name":"jobfrog.session_token","description":"Signed-in staff browser session (same-origin only)"}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}},"ListEnvelope":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"nextCursor":{"type":["string","null"],"description":"Pass as `cursor` for the next page"}}},"ItemEnvelope":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}},"responses":{"Error":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}