Kumo AI Platform
Kumo’s model, planner, durable run loop, approvals, co-signature, artifacts, memory, credits, and tamper-evident audit in one governed platform.
- Named user on every request
- Human gates on commitment
- Complete correlated trace
Embed Kumo's complete model and run loop, point your own agents at Kumo, or connect Kumo to the systems you already run. Every request is a named user; every model call, approval, tool call, receipt, and outcome is traceable.
Tokens are minted per user, per workspace. The API applies the same visibility model as the app: self-service users see themselves, managers their team, HR the workspace. Scopes can only narrow that further.
The REST endpoints, the OpenAPI spec, this reference, and the MCP server's tool list are all generated from the same operation registry the runtime executes. Docs cannot go stale by construction.
Writes run through the platform's own engines: validation, approvals, notifications included. Every MCP call, inbound or outbound, lands in the audit log with who, what, and when.
Four named products, one permission and audit model: Kumo AI Platform, Kumo API, Kumo MCP, and Kumo HR Agent Kit SDK.
Kumo’s model, planner, durable run loop, approvals, co-signature, artifacts, memory, credits, and tamper-evident audit in one governed platform.
Embed the complete Kumo Agent or call individual HR operations through a versioned REST and Agent API with delegated identity.
A matched server, client, and outbound Connector. Your systems call Kumo; Kumo calls the named tools you choose to publish.
A typed TypeScript client, headless controller, and accessible React panel for putting Kumo inside a customer application.
Use Kumo's complete agent in your product, let another agent call Kumo, or let Kumo act across your systems. All three preserve named-user permissions, approvals, credits, and the same tamper-evident audit trail.
Embed
The Agent API and SDK run Kumo's own model, planner, durable loop, approvals, artifacts, and audit trail inside your customer experience.
Embed Kumo →Inbound
Claude Code, Cursor, VS Code, or anything you have built yourself posts JSON-RPC to https://kumohr.com/api/mcp with a personal access token. The tool list is your API, filtered to that token's scopes.
Outbound
An admin connects any MCP server under Settings → Connections: a published URL, or an outbound connector that dials out from inside your network. Every external action waits for a person to approve it.
Set up outbound →Create a token in Kumo under Settings → API access. Pick a name and the scopes it should carry. The secret is shown exactly once. Send it on every request; revoke it any time from the same screen. After you mint one, the same connect buttons appear with the token already filled in.
leave:readRead leave requests and balancesleave:writeCreate leave requestsreports:readRun read-only reportsats:readRead recruiting: jobs, candidates, applications, pipeline stagesats:writeAdd candidates, create applications, move applications between stagesats:assessments:writePost assessment results (AI interviews, tests) back to applicationswebhooks:manageSubscribe to event webhooks and send test eventsats:transcripts:readRead interview transcripts (audit-logged)ats:jobs:writeCreate, draft (with Kumo AI) and publish jobs; set hiring stagesats:assessments:manageCreate and draft (with Kumo AI) screening forms and AI interview plansats:assessments:sendSend Kumo screening assessments and AI interviews to candidatesagent:runStart and continue Kumo agent workagent:readRead agent conversations, runs, and eventsagent:approveApprove or decline agent actionsagent:artifactsUpload inputs and retrieve agent deliverablesaudit:readRead and export the agent audit trailNeed a token? Sign in and open Settings → API access.
This is Kumo's model and durable run loop, not a customer-supplied chatbot. Your backend exchanges one admin-created integration credential for a short-lived credential delegated to an existing Kumo user. Runs inherit that user's live tenant role; scopes can only narrow it.
Personal tokens and admin integration credentials are created under Settings → API access. Secrets are shown once, stored as hashes, independently scoped, expirable, and revocable. Integration credentials stay on your backend; browsers receive only short-lived delegated credentials.
exchange_agent_tokenagent:runPOST /api/v1/agent/tokenlist_agent_threadsagent:readGET /api/v1/agent/threadscreate_agent_threadagent:runPOST /api/v1/agent/threadsget_agent_threadagent:readGET /api/v1/agent/threads/{id}send_agent_messageagent:runPOST /api/v1/agent/threads/{id}/messagesget_agent_runagent:readGET /api/v1/agent/runs/{id}stream_agent_runagent:readGET /api/v1/agent/runs/{id}/eventsdecide_agent_runagent:approvePOST /api/v1/agent/runs/{id}/decisionsanswer_agent_runagent:runPOST /api/v1/agent/runs/{id}/answerscancel_agent_runagent:approvePOST /api/v1/agent/runs/{id}/canceldecide_agent_actionagent:approvePOST /api/v1/agent/runs/{id}/actions/{actionId}/decisionsupload_agent_attachmentagent:artifactsPOST /api/v1/agent/attachmentslist_agent_artifactsagent:artifactsGET /api/v1/agent/artifactsget_agent_artifactagent:artifactsGET /api/v1/agent/runs/{id}/artifacts/{artifactId}download_agent_artifactagent:artifactsGET /api/v1/agent/runs/{id}/artifacts/{artifactId}/downloadlist_agent_auditaudit:readGET /api/v1/agent/auditexport_agent_auditaudit:readGET /api/v1/agent/audit/exportverify_agent_auditaudit:readPOST /api/v1/agent/audit/verifylist_agent_webhooksagent:readGET /api/v1/agent/webhookscreate_agent_webhookagent:runPOST /api/v1/agent/webhooksdisable_agent_webhookagent:runDELETE /api/v1/agent/webhooks/{id}Mutations use Idempotency-Key. Run events are resumable SSE with event IDs. Webhooks are signed and retried. Responses carry request and audit correlation IDs so one external request can be followed through the model, approval, tool, connected system, receipt, artifact, credits, and final outcome.
Point any MCP-capable agent at https://kumohr.com/api/mcp (streamable HTTP, server kumo-hr) with your token in the Authorization header. Protocol versions 2025-06-18 and 2025-03-26. Its tool list is your API: the same operations below, filtered to your token's scopes.
Opens Cursor and asks you to confirm the server.
Any other client reads the same thing from a standard mcp.json:
Your agent can only do what your role allows. The same RBAC that gates the app gates every tool call; the token cannot escalate.
tools/list only advertises operations the token's scopes permit, so an agent holding a read-only token never even sees the write tools.
Every tool call is recorded in the audit log: which token, which tool, which arguments, and whether it succeeded. You can see everything it did.
One tool per operation, named after it. A token only sees the rows its scopes cover. This list is generated from the same registry the server executes.
get_meany tokenGET /api/v1/melist_leave_requestsleave:readGET /api/v1/leave/requestscreate_leave_requestleave:writePOST /api/v1/leave/requestsuntaken_leave_reportreports:readGET /api/v1/reports/untaken-leavelist_ats_jobsats:readGET /api/v1/ats/jobslist_ats_candidatesats:readGET /api/v1/ats/candidatescreate_ats_candidateats:writePOST /api/v1/ats/candidatesimport_ats_candidatesats:writePOST /api/v1/ats/candidates/importlist_ats_applicationsats:readGET /api/v1/ats/applicationscreate_ats_applicationats:writePOST /api/v1/ats/applicationsmove_ats_applicationats:writePOST /api/v1/ats/applications/movelist_ats_pipeline_stagesats:readGET /api/v1/ats/pipeline/stagessearch_candidates_aiats:readPOST /api/v1/ats/candidates/searchlist_webhookswebhooks:manageGET /api/v1/webhookscreate_webhookwebhooks:managePOST /api/v1/webhooksdelete_webhookwebhooks:manageDELETE /api/v1/webhookstest_webhookwebhooks:managePOST /api/v1/webhooks/testrecord_ats_assessmentats:assessments:writePOST /api/v1/ats/assessmentslist_ats_assessmentsats:readGET /api/v1/ats/assessmentslist_ats_assessment_routesats:readGET /api/v1/ats/assessment-routesset_ats_assessment_routeats:writePOST /api/v1/ats/assessment-routesget_ats_candidate_resumeats:readGET /api/v1/ats/candidates/resumeget_ats_assessmentats:readGET /api/v1/ats/assessments/detaildecide_ats_assessmentats:writePOST /api/v1/ats/assessments/decisionget_job_criteriaats:readGET /api/v1/ats/jobs/criteriaset_job_criteriaats:writePOST /api/v1/ats/jobs/criteriamatch_talent_poolats:writePOST /api/v1/ats/jobs/match-poolget_match_resultsats:readGET /api/v1/ats/jobs/match-poolplace_matched_candidatesats:writePOST /api/v1/ats/jobs/match-pool/placedraft_job_with_aiats:jobs:writePOST /api/v1/ats/jobs/draftcreate_jobats:jobs:writePOST /api/v1/ats/jobspublish_jobats:jobs:writePOST /api/v1/ats/jobs/publishset_job_stagesats:jobs:writePOST /api/v1/ats/jobs/stageslist_assessment_templatesats:readGET /api/v1/ats/assessment-templatessave_assessment_templateats:assessments:managePOST /api/v1/ats/assessment-templatesdraft_assessment_with_aiats:assessments:managePOST /api/v1/ats/assessment-templates/draftsend_assessmentats:assessments:sendPOST /api/v1/ats/assessments/send37 operations, and tools only; no MCP resources or prompts yet. Authentication is a personal access token in a header, which covers Cursor, Claude Code, and VS Code. Hosted connectors that require OAuth, such as ChatGPT, cannot connect yet. We would rather say so than ship a button that fails.
Kumo is also an MCP client. An admin allow-lists a server under Settings → Connections. Its tools join the agent's catalogue as mcp__<name>__<tool>. This is how Kumo reaches a calendar, a chat tool, an ERP, an LMS, or anything else that speaks MCP, not a special case for one vendor.
External tools never run unattended. The person sees which system, which operation, and the arguments, then approves. There is no setting that turns this off.
Each call carries who asked, which workspace, and which approved action as headers and JSON-RPC metadata, so it shows against the right name in that system's own audit trail.
Approving a retried step sends the same idempotency key, so an adapter that honours it cannot apply the same change twice.
If the system can publish an https MCP endpoint, register that URL. If it lives on a network that will never accept inbound traffic, add an outbound connector instead: same tools, same approval, no inbound port.
You run a small process beside the system you already have. It dials out to Kumo, publishes the tools on the local adapter, and takes approved calls. No inbound firewall rule, no public URL, no certificate for you to manage.
Add the connector in Settings → Connections. The pairing token is shown once. Point MCP_URL at any local MCP adapter: the system you already run, or a thin wrapper beside it.
Base URL https://kumohr.com. Responses use a { data } / { error: { code, message } } envelope with X-RateLimit-* headers. The machine-readable version of this reference lives at /api/v1/openapi.json.
Returns the authenticated user, workspace (tenant), role, employee id, and the scopes this token carries. Use it to verify a token before wiring anything else.
Lists leave requests you are allowed to see: your own for self-service roles, your team’s for line managers, your department’s for directors, the whole workspace for HR and admins. Filter by status and date range.
statusstringFilter by status. One of: PENDING, APPROVED, REJECTED, CANCELLED, IN_PROGRESS, COMPLETED.fromstringOnly requests ending on or after this date (YYYY-MM-DD).tostringOnly requests starting on or before this date (YYYY-MM-DD).limitnumberMax rows to return (1–200, default 50).Books time off for the token’s user through the platform’s own leave engine. Policy validation, balance movement, approval routing, and notifications all run exactly as from the app. Pass start_date plus either end_date or days; the policy defaults to annual leave.
start_daterequiredstringFirst day off (YYYY-MM-DD).end_datestringLast day off, inclusive (YYYY-MM-DD). Use this OR days.daysnumberNumber of consecutive calendar days off. Use this OR end_date.policystringLeave policy name, e.g. "Annual Leave". Defaults to the annual policy.policy_idstringExact policy id (overrides policy).reasonstringOptional short reason.half_daybooleanTrue for a single half-day request.Per-employee untaken leave for a year: allocated, used, and remaining days with department and manager, sorted by most untaken first. Runs through the same permission-gated reporting tool Kumo’s agent uses. Your role decides whose rows you see.
yearnumberBalance year (defaults to the current year).min_untaken_daysnumberOnly employees with at least this many untaken days.policystringLeave policy name filter (defaults to annual policies).Jobs (requisitions) in the workspace that this token can see. Managers with assigned-only recruiting access see only the jobs they work on.
statusstringFilter by status, e.g. ACTIVE, DRAFT, CLOSED. Default: all.searchstringFree-text search over title and requisition code.pagenumberPage number, from 1.limitnumberRows per page (1–100, default 25).Candidates in the talent pool, with their applications. Pass `email` for an exact lookup (the way to check whether a candidate already exists).
emailstringExact email match.searchstringFree-text search over name, email and title.stagestringOnly candidates currently in this stage.statusstringCandidate status, e.g. NEW, ACTIVE, HIRED, REJECTED.pagenumberPage number, from 1.limitnumberRows per page (1–100, default 25).Adds a candidate, or updates them if they already exist. Kumo matches first on `source_system` + `external_id` (your system’s id, so a changed email still finds the same person), then on email; a match is updated with the fields you send and returned with `created: false`. Attach a CV with `resume_url` (an https link Kumo downloads) or `resume_base64`: PDF or Word, up to 10 MB. A new or changed CV is scored against the job and your company; an unchanged CV is not re-scored. Pass `job_id` to apply them to a job (the application starts in the job’s first stage).
first_namerequiredstringFirst name.last_namerequiredstringLast name.emailrequiredstringEmail address — the dedupe key.phonestringPhone number, with country code.locationstringCity and/or country.current_titlestringCurrent job title.current_companystringCurrent employer.linkedin_urlstringLinkedIn profile URL.skillsstringSkills, comma-separated (or a JSON array of strings).tagsstringTags, comma-separated (or a JSON array of strings).notesstringFree-text recruiter notes.sourcestringWhere the candidate came from, shown to recruiters. Default: the source_system name, or API.source_systemstringYour system, e.g. "greenhouse" or "client-ats". With external_id, the match key.external_idstringThe candidate’s id in your system. Sending the same one again updates the same candidate.resume_urlstringhttps link to the CV (PDF or Word, up to 10 MB). Kumo downloads it once.resume_base64stringThe CV file itself, base64-encoded, instead of resume_url. Requests are limited to about 4.5 MB, so use resume_url for CVs over about 3 MB.resume_filenamestringFile name for the CV, e.g. "jane-doe.pdf".job_idstringAlso apply the candidate to this job.Up to 100 candidates per call, each handled exactly like “Add a candidate” (matched on source_system + external_id, then email; CVs by link or base64). `job_id`, `source_system` and `source` at the top level apply to every candidate unless a candidate sets its own. One bad candidate never fails the others: each result says ok or why not.
candidatesrequiredarrayThe candidates: the same fields as “Add a candidate”.job_idstringApply every candidate to this job.source_systemstringYour system, for every candidate.sourcestringWhere they came from, for every candidate.Applications — a candidate applied to a job — with their current pipeline stage. Filter by job to read a job’s board.
job_idstringOnly applications to this job.candidate_idstringOnly this candidate’s applications.stagestringOnly applications in this stage.statusstringApplication status, e.g. NEW, INTERVIEW, OFFER, HIRED, REJECTED.pagenumberPage number, from 1.limitnumberRows per page (1–100, default 25).Creates an application for an existing candidate. Idempotent per candidate and job. Pass `stage` to place it straight into a pipeline stage (for example after your own screening); otherwise it starts in the job’s first stage.
candidate_idrequiredstringThe candidate.job_idrequiredstringThe job.stagestringPipeline stage to place the application in. See list_ats_pipeline_stages.sourcestringWhere the application came from. Default: API.Moves one application to another stage of its job’s pipeline — the same as dragging the card on the board, with the same activity log. The stage must be one of the job’s stages (see list_ats_pipeline_stages); other applications of the candidate are not touched.
application_idrequiredstringThe application to move.stagerequiredstringTarget stage name (case-insensitive).reasonstringOptional note for the activity log.The stages an application can move through. With `job_id`, the job’s own pipeline when it has one; otherwise the workspace’s default pipeline.
job_idstringThe job whose pipeline to read.Search the whole talent pool the way a recruiter would ask: "senior data engineers in Jakarta with Spark", or pass `job_id` to rank the pool against that job’s criteria. Returns people best first with matched skills and reasons. Pass `required_skills`/`preferred_skills`/`locations`/`min_years` yourself to skip Kumo’s request parsing (no AI credits); otherwise parsing is one metered call billed to the workspace, and `explain: true` adds a one-line reason per result (one more call). Requests that filter on age, gender, religion, nationality, marital status, health or appearance are refused with 422.
querystringWho you are looking for, in plain words.job_idstringRank the pool for this job (its criteria and stored fit scores).required_skillsarraySkills every result must have (up to 3).preferred_skillsarraySkills that rank people higher (up to 8).locationsarrayCities, regions or countries.min_yearsnumberMinimum years of experience (people with no recorded experience are kept, ranked lower).filtersobjectHard filters: {skills, locations, minYears, maxYears, sources, tags, appliedToJobId, hasCv, activeWithinDays}.modestring`ai` (default) parses the query with a model; `basic` never calls a model. One of: ai, basic.explainbooleanAdd a one-line reason and a profile quote per result (metered).limitnumberResults to return, 1-50 (default 20).Active webhook endpoints in the workspace, their filters, and the 50 most recent deliveries with status and response code.
Registers an https endpoint for signed event deliveries. Narrow it with `filters` — e.g. `{"stages":["AI Interview"]}` delivers only when an application enters that stage. The `signing_secret` is returned once; use it to verify the `Kumo-Webhook-Signature` header.
urlrequiredstringYour https endpoint.eventsrequiredstringEvent types (JSON array or comma-separated). Recruiting: ats.application.stage_entered, ats.application.created, ats.assessment.recorded, ats.assessment.invited, ats.assessment.started, ats.assessment.declined, ats.job.created, ats.job.published.filtersobjectOptional: {"stages": [stage names], "job_ids": [job ids]}.labelstringA name for this endpoint.Stops deliveries to an endpoint. Pending deliveries to it are dropped.
idrequiredstringThe webhook id.Sends a signed sample `ats.application.stage_entered` event (marked `"test": true`, with sample candidate and job data) to the endpoint right away and reports what your server answered.
idrequiredstringThe webhook id.Records a result from your assessment (AI interview, test, check) against an application. Idempotent by `provider` + `external_id`: post each status change for the same session and it updates one record. When `status` is `completed` and the workspace has a route for the application’s current stage, Kumo moves the application to the pass or fail stage (from `passed`, or `score` against the route’s minimum) — unless a recruiter has already moved it.
application_idrequiredstringThe application (from the webhook payload).providerrequiredstringYour product key, e.g. "genia". Stable across calls.external_idrequiredstringYour id for this session or test.statusrequiredstringWhere the assessment is. One of: pending, invited, in_progress, completed, expired, declined, cancelled, error.scorenumberOverall score, 0–100.passedbooleanYour recommendation. Omit to let the route’s minimum score decide.summarystringConclusion shown to recruiters.strengthsstringStrengths.weaknessesstringWeaknesses / concerns.report_urlstringhttps link to the full report or recording.rawobjectYour full result as JSON (up to 256 KB), kept for recruiters.recommendationstringYour recommendation for the recruiter. One of: advance, hold, reject.confidencenumberHow sure you are, 0–1.modestringHow the interview ran. One of: voice, text.disclosureobjectWhat you told the candidate before starting: {text, version?, language?: en|id, mode?: voice|text, shown_at?}. Shown to recruiters as “What they were told”.preferred_humanbooleanWith status "declined": the candidate asked to speak with a person. Never scored; the hiring team is told.sentimentobjectYour sentiment read, if you produce one: a label such as "positive", or {label, score?: -100 to 100, notes?}. Shown to recruiters as context; never used to move a candidate.kindstringai_interview (default), skills_test, async_video, reference_check or custom.dimension_scoresarrayPer-dimension scores shown as bars: [{key, label, score 0-100, weight?, evidence: [{quote, t_ms?}]}] (up to 20).transcriptarrayThe interview transcript: [{role: interviewer|candidate, text, t_ms?}] (up to 400 turns). Evidence timestamps jump to it.Assessment results recorded for an application or candidate, newest first.
application_idstringResults for this application.candidate_idstringResults for this candidate.Where completed assessments send applications: for each trigger stage, the pass and fail stages.
Sets where a completed assessment sends an application that is in `trigger_stage`. Workspace-wide by default; pass `job_id` for one job and `provider` for one partner. Replaces any existing route for the same job, provider and trigger stage. Workspace admins only.
trigger_stagerequiredstringThe stage the assessment runs in, e.g. "AI Interview".pass_stagerequiredstringWhere a pass goes.fail_stagerequiredstringWhere a fail goes.min_scorenumberPass mark (0–100) used when a result has a score but no `passed`.job_idstringOnly for this job.providerstringOnly for results from this provider.fail_policystringOn a fail: move_and_review (default: move to the fail stage and flag for a recruiter), move, or review (keep the card where it is until a recruiter decides). One of: move_and_review, move, review.A download link for the candidate’s CV that expires after 15 minutes. Webhook payloads carry this path in `links.resume` rather than a file or a long-lived link. Needs full recruiting access.
candidate_idrequiredstringThe candidate.One assessment result with dimension scores, recommendation and review state. Add `include=transcript` for the transcript (needs the ats:transcripts:read scope; every read is audit-logged).
idrequiredstringThe assessment id.includestringComma-separated extras: transcript.For partners with their own review screen: advance (to the route’s pass stage), reject (to its fail stage) or hold. Going against the result’s recommendation needs a reason. Marks the result reviewed.
idrequiredstringThe assessment id.decisionrequiredstringThe decision. One of: advance, hold, reject.reasonstringWhy (required when overriding the recommendation).The criteria a job is scored against, with importance, weight, knockout flag and any fairness warnings. `defined: false` means they were derived from the job’s listed skills and the workspace has not saved its own yet.
job_idrequiredstringThe job.Replaces a job’s criteria. Up to 30; `importance` is must_have, important or nice_to_have; `knockout` applies to must-haves only and flags candidates for review — nobody is rejected automatically. Criteria that could discriminate (age, gender, “native speaker”…) are refused unless `lint_justification` gives a job-related reason. Changing weights or importance re-scores for free; new or reworded criteria are assessed on the next scoring run.
job_idrequiredstringThe job.criteriarequiredarrayList of {label, category?, importance?, weight?, knockout?, min_years?, evidence_hint?, lint_justification?}.match_thresholdnumberJob-fit score (0–100) for talent-pool placement. Null uses the workspace default.Scores every candidate in the workspace’s talent pool against the job’s criteria, in the background. Candidates already scored for the current criteria cost nothing. Poll get_match_results for progress and the ranking; nothing is placed until you call place_matched_candidates.
job_idrequiredstringThe job.Progress of the latest match run for a job, and candidates ranked by job-fit score with must-have status and whether they are already in the pipeline.
job_idrequiredstringThe job.Creates an application in the job’s first stage (e.g. “Matched Profile”) for each candidate. Candidates already in the pipeline are skipped. Emits ats.application.created.
job_idrequiredstringThe job.candidate_idsrequiredarrayCandidates to place (up to 500).Describe the role in plain words ("senior data engineer, hybrid Jakarta, Python/Spark/Airflow") and Kumo drafts the whole job: the ad, hiring criteria, application questions, the hiring stages and an assessment per stage (a screening form or an AI interview). When required facts are missing it returns `needs_input: true` with up to three `follow_ups`; send the answers back in `answers` (keyed by follow-up id; answer `skip` for optional ones). Nothing is saved — pass the draft to `create_job`. Metered: about 1 credit to read the brief and 2 per drafting call (typically 8-12 credits for a full job), billed to the workspace. AI-written screening forms are created as drafts that a person must approve before they can be sent.
briefrequiredstringWhat you are hiring for, in your own words (any language).answersobjectAnswers to earlier follow-ups: {title, seniority, where, salary}.Create a job (as a draft unless `publish: true`) from a `draft` returned by `draft_job_with_ai`, or from your own fields. Stages, criteria, application questions and each stage’s assessment are saved in the same call; stage assessments become stage automations (sent automatically when a candidate enters the stage, with pass/fail routing and fails held for review by default). Approval policies still apply: a job that needs approval is created and waits. No AI credits are used.
draftobjectA draft from draft_job_with_ai (edited as you like).titlestringWithout a draft: the job title.departmentstringWithout a draft: the department.locationstringCity or office (required unless remote).work_arrangementstringOnsite, Hybrid or Remote. One of: Onsite, Hybrid, Remote.descriptionstringThe job ad (HTML or text).stagesarrayHiring stages: [{name, objective?, assessment?: {type: none|form|ai_interview|template|partner, …}, pass_stage?, fail_policy?}].requisition_codestringYour own requisition number (e.g. from your HR system). Omit and Kumo numbers it (REQ-2026-0042). Unique per workspace.publishbooleanPublish immediately (subject to approval).Take a draft job live on the careers page. Refused with 409 while the job waits for approval. A job with no stages gets the workspace’s default stages.
job_idrequiredstringThe job.Replace a job’s stage plan safely: stages are matched by id or name and updated in place, so candidates already in a stage keep their place; a removed stage that still has history is deactivated, not deleted; renames carry over to automations and routing. Each stage can carry an assessment (`form`, `ai_interview`, an existing `template`, or a `partner`), which becomes its stage automation.
job_idrequiredstringThe job.stagesrequiredarray[{id?, name, objective?, assessment?, pass_stage?, fail_stage?, fail_policy?}] in order.Screening forms and AI interview plans — a job’s own plus the workspace library — with the credit cost per candidate.
job_idstringOnly this job’s templates (and the library).kindstringform or ai_interview. One of: form, ai_interview.A screening form (`kind: form`: knockout, single/multi choice with right answers or points, number ranges, short/long written answers with a rubric) or an AI interview plan (`kind: ai_interview`). Pass `id` to update; candidates who already have a link keep the version they were sent. Questions about protected characteristics are rejected. Set `status: active` to approve a draft (AI-written forms start as drafts).
idstringUpdate this template.job_idstringAttach to a job (omit for the workspace library).kindstringform or ai_interview. One of: form, ai_interview.namerequiredstringName shown to candidates.configrequiredobjectThe questions or interview plan (see the example).statusstringdraft or active. One of: draft, active.Kumo writes a screening form (scenario questions at the job’s seniority, answer keys double-checked, debatable questions removed) or an AI interview plan for a job and stage. Nothing is saved — pass the result to `save_assessment_template`. Metered (about 3 credits for a form, 2 for an interview plan).
kindrequiredstringform or ai_interview. One of: form, ai_interview.job_idstringThe job to write it for.stagestringThe stage it is for.instructionsstringWhat to focus on, in plain words.currentobjectAn existing config to improve instead of starting fresh.Send a screening form or a Kumo AI interview (text or voice) for one application. Returns the candidate’s private link so you can deliver it yourself (`send_email: false`), or Kumo emails it in the workspace’s branding. Idempotent while the invite is open; `rotate_link: true` issues a fresh link. Someone who already completed it is not asked again (`already_done: true`) unless you pass `retake: true`. The result arrives as `ats.assessment.recorded` and routes like any assessment. Refused with 402 when the workspace is out of credits (written answers and interviews are scored by AI).
application_idrequiredstringThe application.template_idrequiredstringThe assessment template.send_emailbooleanKumo emails the link (default true).expires_in_daysnumber1-21 (default 7).rotate_linkbooleanIssue a new link for an open invite.retakebooleanSend again to someone who already completed it (default false).REST failures use the { error: { code, message } } envelope. Over MCP the same failures come back as a tool result with isError set, so your agent can read the reason rather than crashing. GET https://kumohr.com/api/mcp returns 405; this server is POST-only. Unauthenticated calls return 401 with WWW-Authenticate.
401Missing, invalid, revoked, or expired token403Token is missing the required scope, or the user's role lacks access429Over 60 requests per minute for this token; see the Retry-After headerEvery REST response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset, so you can back off before you get there.