Kumo developer documentation

Build with the Kumo Agent Platform.

Embed Kumo's complete agent, call individual HR operations, connect another agent over MCP, or let Kumo act through tools you publish. This is the full public contract, with runnable requests and real response shapes.

agent.ts
const kumo = new KumoAgentClient({
  token: delegated.accessToken
});

const thread = await kumo.createThread({
  title: "New-starter readiness"
});

const result = await kumo.sendMessage(
  thread.data.thread.id,
  { message: "Check Monday's starters." }
);

for await (const event of kumo.streamRun(
  result.data.runId
)) {
  console.log(event);
}
25 documented operations8 granular scopesResumable SSESigned webhooksMCP both ways
Overview

One platform, four ways to use it.

All Kumo surfaces share one identity and governance model. Every request is attached to a named Kumo user. Scopes can narrow that user's live role; they can never widen it.

01

Embed Kumo

Use the Agent API and Agent Kit SDK. Kumo's model plans and runs the work.

Agent quickstart →
02

Call Kumo

Use versioned REST endpoints for focused, permission-aware HR operations.

REST reference →
03

Connect an agent

Point Cursor, Claude Code, VS Code, or your own MCP client at Kumo.

Inbound MCP →
04

Connect a system

Register a published MCP server or run the outbound Connector privately.

Outbound MCP →
Quickstart

Run Kumo from your application.

Create an admin integration credential under Settings → API access. Keep it on your backend, exchange it for a short-lived named-user credential, then create a thread and send work to Kumo.

  1. 1
    Create credentials

    Select Integration and grant only the scopes your application needs.

  2. 2
    Delegate to a user

    Exchange on your backend. The user must already belong to the Kumo workspace.

  3. 3
    Create a thread

    Threads hold conversational continuity across messages and runs.

  4. 4
    Stream the run

    Use SSE for live progress and reconnect from the last event id.

  5. 5
    Present decisions

    Show approval or co-sign cards instead of auto-accepting actions.

Install
npm install @kumohr/agent-sdk
Server-side credential exchange
import { KumoAgentClient } from "@kumohr/agent-sdk";

const integration = new KumoAgentClient({
  token: process.env.KUMO_INTEGRATION_CREDENTIAL!
});

const delegated = await integration.exchangeCredential({
  userId: kumoUserId,
  externalSessionId: yourSession.id,
  scopes: [
    "agent:run",
    "agent:read",
    "agent:approve",
    "agent:artifacts"
  ]
});
Run and stream
const kumo = new KumoAgentClient({
  token: delegated.accessToken
});

const created = await kumo.createThread({
  title: "New-starter readiness"
});

const result = await kumo.sendMessage(
  created.data.thread.id,
  {
    message:
      "Check Monday's starters and prepare missing actions."
  }
);

if (result.data.kind === "run") {
  for await (const event of kumo.streamRun(
    result.data.runId
  )) {
    renderAgentEvent(event);
  }
}
SDK distribution

The Agent Kit package is currently distributed during technical onboarding. The REST and MCP contracts are public and usable without the SDK.

Authentication

Credentials identify a real user.

Kumo never runs an anonymous service agent. Credentials are workspace-bound, revocable, expirable, and shown once.

CredentialPrefixUseLifetime
Personal access tokenkumo_

REST, MCP, development, and user-owned integrations

30–365 days
Integration credentialkumo_app_

Customer backend; exchanges for delegated credentials

30–365 days
Delegated credentialkumo_dlg_

Short-lived application session for one existing user

15 minutes

Send the credential

Authorization header
Authorization: Bearer kumo_YOUR_TOKEN

Available scopes

leave:readRead leave requests and balances
leave:writeCreate leave requests
reports:readRun read-only reports
agent:runStart and continue Kumo agent work
agent:readRead agent conversations, runs, and events
agent:approveApprove or decline agent actions
agent:artifactsUpload inputs and retrieve agent deliverables
audit:readRead and export the agent audit trail
Permission rule

A scope grants no role permission by itself. Kumo resolves the user's current workspace role on every call, then intersects it with the credential scopes.

API conventions

Predictable by default.

Base URL

https://kumohr.com

All versioned REST routes begin with /api/v1.

JSON envelope

{ data, requestId }

Failures return { error: { code, message } }.

Idempotency

Idempotency-Key

Required on Agent API mutations. Reuse only for an identical request.

Correlation

auditCorrelationId

Joins the external request to model, approval, tool, receipt, and outcome events.

Rate limit

60/minute

Per credential. Respect Retry-After on HTTP 429.

Time and IDs

ISO 8601 · opaque IDs

Timestamps are UTC. Treat every identifier as an opaque string.

Rate-limit headers

Response headers
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 42
Retry-After: 42  # only on 429
Agent lifecycle

From message to provable outcome.

01Message

Kumo reads the user request and owned attachments.

02Plan

The model proposes a durable, permission-aware run.

03Approval

A person starts the plan and decides every committed action.

04Execution

Native and connected tools run with idempotency and attribution.

05Artifact

Reports, tables, charts, and files remain attached to the run.

06Audit

The full trace is encrypted, correlated, hash-chained, and exportable.

Run statuses

draftawaiting_inputawaiting_approvalrunningawaiting_externalcompleted

A run may finish as failed or cancelled from any non-terminal stage. Parked external work resumes from a durable checkpoint.

API reference

Every public endpoint.

Search the complete Agent API and focused REST surface. Expand an operation for parameters, behavioral notes, a runnable cURL request, and a real response shape.

Complete reference25 documented operations

Credentials

1
POST/api/v1/agent/tokenExchange an integration credentialagent:run

Issue a short-lived credential delegated to an existing named Kumo user. The user must already belong to the integration credential’s workspace.

Important

  • Call this from your backend. Never put an integration credential in browser code.
  • Requested scopes are intersected with the integration credential’s scopes.
Request
curl -X POST "https://kumohr.com/api/v1/agent/token" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
  "userId": "usr_8f2b…",
  "externalSessionId": "portal-session-01839",
  "scopes": [
    "agent:run",
    "agent:read",
    "agent:approve",
    "agent:artifacts"
  ]
}'
Response
{
  "tokenType": "Bearer",
  "accessToken": "kumo_dlg_…",
  "expiresAt": "2026-08-21T10:30:00.000Z",
  "userId": "usr_8f2b…",
  "tenantId": "tenant_42ac…",
  "scopes": [
    "agent:run",
    "agent:read",
    "agent:approve",
    "agent:artifacts"
  ],
  "auditCorrelationId": "2b90…"
}

Threads

4
GET/api/v1/agent/threadsList agent threadsagent:read

List the delegated user’s Kumo conversations, newest activity first.

Request
curl "https://kumohr.com/api/v1/agent/threads" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN"
Response
{
  "data": {
    "threads": [
      {
        "id": "thread_19d0…",
        "title": "New-starter readiness",
        "createdAt": "2026-08-21T09:00:00.000Z",
        "updatedAt": "2026-08-21T09:08:00.000Z",
        "lastRun": {
          "id": "run_e75f…",
          "title": "Check new starters",
          "status": "completed"
        }
      }
    ]
  },
  "requestId": "req_…"
}
POST/api/v1/agent/threadsCreate an agent threadagent:run

Create a conversation for embedded Kumo work.

Request
curl -X POST "https://kumohr.com/api/v1/agent/threads" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id" \
  --data '{
  "title": "New-starter readiness"
}'
Response
{
  "data": {
    "thread": {
      "id": "thread_19d0…",
      "title": "New-starter readiness",
      "createdAt": "2026-08-21T09:00:00.000Z",
      "updatedAt": "2026-08-21T09:00:00.000Z",
      "lastRun": null
    }
  },
  "requestId": "req_…",
  "auditCorrelationId": "88a1…"
}
GET/api/v1/agent/threads/{id}Get an agent threadagent:read

Read a conversation and its ordered user, assistant, and run turns.

Request
curl "https://kumohr.com/api/v1/agent/threads/RESOURCE_ID" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN"
Response
{
  "data": {
    "thread": {
      "id": "thread_19d0…",
      "title": "New-starter readiness"
    },
    "turns": [
      {
        "id": "turn_1",
        "role": "user",
        "content": "Check whether Monday’s starters are ready.",
        "runId": null,
        "createdAt": "2026-08-21T09:01:00.000Z"
      },
      {
        "id": "turn_2",
        "role": "run",
        "content": null,
        "runId": "run_e75f…",
        "run": {
          "id": "run_e75f…",
          "title": "Check new starters",
          "status": "completed"
        }
      }
    ]
  },
  "requestId": "req_…"
}
POST/api/v1/agent/threads/{id}/messagesSend a message to Kumoagent:run

Let Kumo reply conversationally or plan a durable agent run using Kumo’s model runtime.

Important

  • A conversational answer returns HTTP 200 with `kind: reply`; a planned run returns HTTP 202.
Request
curl -X POST "https://kumohr.com/api/v1/agent/threads/RESOURCE_ID/messages" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id" \
  --data '{
  "message": "Check whether Monday’s starters are ready and prepare the missing actions.",
  "attachmentIds": [
    "attachment_c32d…"
  ]
}'
Response
{
  "data": {
    "kind": "run",
    "runId": "run_e75f…",
    "detail": {
      "run": {
        "id": "run_e75f…",
        "status": "awaiting_approval"
      },
      "steps": [
        {
          "id": "step_1",
          "title": "Read upcoming starters",
          "status": "pending"
        }
      ],
      "actions": [],
      "artifacts": [],
      "auditCorrelationId": "bc13…"
    }
  },
  "requestId": "req_…"
}

Runs

5
GET/api/v1/agent/runs/{id}Get an agent runagent:read

Read the plan, events, pending actions, and artifacts for one owned run.

Request
curl "https://kumohr.com/api/v1/agent/runs/RESOURCE_ID" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN"
Response
{
  "data": {
    "run": {
      "id": "run_e75f…",
      "title": "Check new starters",
      "status": "awaiting_approval",
      "createdAt": "2026-08-21T09:01:00.000Z"
    },
    "steps": [
      {
        "id": "step_1",
        "title": "Read upcoming starters",
        "status": "pending"
      }
    ],
    "events": [
      {
        "id": "18201",
        "type": "plan_proposed",
        "payload": {
          "stepCount": 3
        }
      }
    ],
    "actions": [],
    "artifacts": []
  },
  "requestId": "req_…"
}
GET/api/v1/agent/runs/{id}/eventsStream agent run eventsagent:read

Open a resumable Server-Sent Events stream. Use the SSE `id` or `?cursor=` value to continue without losing events.

Important

  • Events include `status`, `agent.event`, `heartbeat`, `done`, and `error`.
  • Reconnect with `?cursor=<last-event-id>` after a transport interruption.
Connect
curl "https://kumohr.com/api/v1/agent/runs/RESOURCE_ID/events" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN"
Event stream
id: 18202\nevent: agent.event\ndata: {"id":"18202","type":"step_started","payload":{"title":"Read upcoming starters"}}\n\n
POST/api/v1/agent/runs/{id}/decisionsApprove or cancel a runagent:approve

Record the named user’s plan decision and start or cancel the run.

Important

  • Use `cancel` here before execution, or the dedicated cancel endpoint at any non-terminal stage.
Request
curl -X POST "https://kumohr.com/api/v1/agent/runs/RESOURCE_ID/decisions" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id" \
  --data '{
  "decision": "approve"
}'
Response
{
  "data": {
    "runId": "run_e75f…",
    "decision": "approve",
    "status": "running"
  },
  "requestId": "req_…",
  "auditCorrelationId": "e21d…"
}
POST/api/v1/agent/runs/{id}/answersAnswer Kumoagent:run

Answer a clarification and resume planning or execution.

Request
curl -X POST "https://kumohr.com/api/v1/agent/runs/RESOURCE_ID/answers" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id" \
  --data '{
  "answer": "Use the London onboarding template."
}'
Response
{
  "data": {
    "runId": "run_e75f…",
    "status": "awaiting_approval"
  },
  "requestId": "req_…",
  "auditCorrelationId": "39fe…"
}
POST/api/v1/agent/runs/{id}/cancelCancel an agent runagent:approve

Cancel a non-terminal run and preserve the reason in the audit ledger.

Request
curl -X POST "https://kumohr.com/api/v1/agent/runs/RESOURCE_ID/cancel" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id" \
  --data '{
  "reason": "The source data is being corrected."
}'
Response
{
  "data": {
    "runId": "run_e75f…",
    "status": "cancelled"
  },
  "requestId": "req_…",
  "auditCorrelationId": "72ac…"
}

Actions

1
POST/api/v1/agent/runs/{id}/actions/{actionId}/decisionsDecide an agent actionagent:approve

Approve, decline, retry, interrupt, or co-sign a pending action.

Important

  • `cosign` requires a second, distinct elevated user.
  • External MCP actions always require explicit approval.
Request
curl -X POST "https://kumohr.com/api/v1/agent/runs/RESOURCE_ID/actions/ACTION_ID/decisions" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id" \
  --data '{
  "decision": "approve"
}'
Response
{
  "data": {
    "actionId": "action_4be2…",
    "decision": "approve",
    "status": "done",
    "summary": "Manager nudges prepared."
  },
  "requestId": "req_…",
  "auditCorrelationId": "adc1…"
}

Files

4
POST/api/v1/agent/attachmentsUpload an agent attachmentagent:artifacts

Upload and extract a file for the next Kumo message using multipart form data.

Important

  • Use the returned attachment id in `send_agent_message.attachmentIds`.
Request
curl -X POST "https://kumohr.com/api/v1/agent/attachments" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN" \
  -F "file=@document.pdf"
Response
{
  "data": {
    "attachment": {
      "id": "attachment_c32d…",
      "name": "onboarding-plan.pdf",
      "mime": "application/pdf",
      "sizeBytes": 84211,
      "status": "ready",
      "summary": "Onboarding plan for the London cohort."
    }
  },
  "requestId": "req_…",
  "auditCorrelationId": "a67b…"
}
GET/api/v1/agent/artifactsList agent artifactsagent:artifacts

List deliverables produced for the delegated user. Use `?limit=1..100`.

Request
curl "https://kumohr.com/api/v1/agent/artifacts" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN"
Response
{
  "data": {
    "artifacts": [
      {
        "runId": "run_e75f…",
        "runTitle": "Check new starters",
        "artifact": {
          "id": "artifact_41dd…",
          "kind": "summary",
          "title": "New-starter readiness",
          "createdAt": "2026-08-21T09:07:00.000Z"
        }
      }
    ]
  },
  "requestId": "req_…"
}
GET/api/v1/agent/runs/{id}/artifacts/{artifactId}Get an agent artifactagent:artifacts

Retrieve one owned run artifact and its structured body.

Request
curl "https://kumohr.com/api/v1/agent/runs/RESOURCE_ID/artifacts/ARTIFACT_ID" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN"
Response
{
  "data": {
    "artifact": {
      "id": "artifact_41dd…",
      "kind": "summary",
      "title": "New-starter readiness",
      "body": {
        "markdown": "# Readiness\\n\\nThree starters are ready; one needs equipment."
      }
    }
  },
  "requestId": "req_…"
}
GET/api/v1/agent/runs/{id}/artifacts/{artifactId}/downloadDownload an agent artifactagent:artifacts

Download an owned deliverable as Markdown, CSV, or JSON.

Important

  • Use `?format=md`, `?format=csv`, or `?format=json`.
Request
curl "https://kumohr.com/api/v1/agent/runs/RESOURCE_ID/artifacts/ARTIFACT_ID/download" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN"
Response
Binary response with Content-Disposition attachment

Audit

3
GET/api/v1/agent/auditRead the agent audit ledgeraudit:read

Read decrypted tenant-visible events with request, run, action, tool, and integrity correlation.

Important

  • Filter with `after`, `runId`, `actionId`, `requestId`, and `limit` (maximum 200).
Request
curl "https://kumohr.com/api/v1/agent/audit" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN"
Response
{
  "data": {
    "events": [
      {
        "id": "291",
        "sequence": "84",
        "eventType": "agent.action.approve",
        "outcome": "success",
        "requestId": "req_…",
        "runId": "run_e75f…",
        "actionId": "action_4be2…",
        "eventHash": "adc1…",
        "occurredAt": "2026-08-21T09:06:00.000Z"
      }
    ],
    "nextCursor": "84"
  },
  "requestId": "req_…"
}
GET/api/v1/agent/audit/exportExport signed agent auditaudit:read

Admin-only signed manifest for the tenant’s hash-chained ledger.

Request
curl "https://kumohr.com/api/v1/agent/audit/export" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN"
Response
{
  "manifest": {
    "version": 1,
    "tenantId": "tenant_42ac…",
    "eventCount": 84,
    "rootHash": "f19a…",
    "integrity": {
      "ok": true,
      "brokenAt": null
    }
  },
  "signature": "HMAC-SHA256 signature",
  "algorithm": "HMAC-SHA256"
}
POST/api/v1/agent/audit/verifyVerify an audit exportaudit:read

Verify a signed manifest against Kumo’s audit signing key.

Request
curl -X POST "https://kumohr.com/api/v1/agent/audit/verify" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
  "manifest": {
    "version": 1,
    "tenantId": "tenant_42ac…"
  },
  "signature": "…"
}'
Response
{
  "data": {
    "valid": true,
    "tenantId": "tenant_42ac…",
    "checkedAt": "2026-08-21T09:10:00.000Z"
  },
  "requestId": "req_…"
}

Webhooks

3
GET/api/v1/agent/webhooksList agent webhooksagent:read

List event endpoints, recent delivery attempts, and supported event names.

Request
curl "https://kumohr.com/api/v1/agent/webhooks" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN"
Response
{
  "data": {
    "endpoints": [
      {
        "id": "webhook_a10c…",
        "label": "Customer portal",
        "url": "https://example.com/kumo/events",
        "enabled": true,
        "events": [
          "agent.run.completed",
          "agent.action.required"
        ]
      }
    ],
    "deliveries": [],
    "supportedEvents": [
      "agent.run.completed",
      "agent.run.failed",
      "agent.run.cancelled",
      "agent.action.required",
      "agent.artifact.created",
      "agent.connector.health"
    ]
  },
  "requestId": "req_…"
}
POST/api/v1/agent/webhooksCreate an agent webhookagent:run

Create a signed HTTPS event endpoint. The signing secret is returned once.

Important

  • Store the signing secret immediately. Kumo never returns it again.
Request
curl -X POST "https://kumohr.com/api/v1/agent/webhooks" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id" \
  --data '{
  "label": "Customer portal",
  "url": "https://example.com/kumo/events",
  "events": [
    "agent.run.completed",
    "agent.action.required"
  ]
}'
Response
{
  "data": {
    "endpoint": {
      "id": "webhook_a10c…",
      "label": "Customer portal",
      "url": "https://example.com/kumo/events",
      "events": [
        "agent.run.completed",
        "agent.action.required"
      ],
      "enabled": true
    },
    "signingSecret": "kumo_wh_…"
  },
  "requestId": "req_…",
  "auditCorrelationId": "eb91…"
}
DELETE/api/v1/agent/webhooks/{id}Disable an agent webhookagent:run

Stop future deliveries without deleting delivery history.

Request
curl -X DELETE "https://kumohr.com/api/v1/agent/webhooks/RESOURCE_ID" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN" \
  -H "Idempotency-Key: unique-request-id"
Response
{
  "data": {
    "id": "webhook_a10c…",
    "enabled": false
  },
  "requestId": "req_…"
}

REST · Identity

1
GET/api/v1/meIntrospect the tokenany valid token

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.

Request
curl "https://kumohr.com/api/v1/me" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN"
Response
{
  "data": {
    "token": {
      "name": "Zapier integration",
      "scopes": [
        "leave:read",
        "reports:read"
      ]
    },
    "user": {
      "id": "uuid",
      "name": "Amara Okafor",
      "email": "amara@acme.com",
      "role": "HR_MANAGER"
    },
    "tenant": {
      "id": "uuid",
      "name": "Acme Ltd"
    },
    "employee_id": 214
  }
}

REST · Leave

2
GET/api/v1/leave/requestsList leave requestsleave:read

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.

Parameters

statusquerystring

Filter by status. Values: PENDING, APPROVED, REJECTED, CANCELLED, IN_PROGRESS, COMPLETED.

fromquerystring

Only requests ending on or after this date (YYYY-MM-DD).

toquerystring

Only requests starting on or before this date (YYYY-MM-DD).

limitquerynumber

Max rows to return (1–200, default 50).

Request
curl "https://kumohr.com/api/v1/leave/requests" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN"
Response
{
  "data": {
    "requests": [
      {
        "id": "uuid",
        "employee_id": 214,
        "employee_name": "Amara Okafor",
        "policy": "Annual Leave",
        "start_date": "2026-09-07",
        "end_date": "2026-09-11",
        "total_days": 5,
        "half_day": false,
        "status": "APPROVED",
        "reason": "Family trip",
        "created_at": "2026-08-30T09:15:00.000Z"
      }
    ]
  }
}
POST/api/v1/leave/requestsCreate a leave requestleave:write

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.

Parameters

start_datebodyrequiredstring

First day off (YYYY-MM-DD).

end_datebodystring

Last day off, inclusive (YYYY-MM-DD). Use this OR days.

daysbodynumber

Number of consecutive calendar days off. Use this OR end_date.

policybodystring

Leave policy name, e.g. "Annual Leave". Defaults to the annual policy.

policy_idbodystring

Exact policy id (overrides policy).

reasonbodystring

Optional short reason.

half_daybodyboolean

True for a single half-day request.

Request
curl -X POST "https://kumohr.com/api/v1/leave/requests" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id" \
  --data '{
  "start_date": "2026-09-07",
  "end_date": "2026-09-07",
  "days": 2,
  "policy": "Annual Leave",
  "policy_id": "value",
  "reason": "Family trip",
  "half_day": false
}'
Response
{
  "data": {
    "id": "uuid",
    "status": "PENDING",
    "policy": "Annual Leave",
    "start_date": "2026-09-07",
    "end_date": "2026-09-08",
    "total_days": 2,
    "warnings": []
  }
}

REST · Reports

1
GET/api/v1/reports/untaken-leaveUntaken leave reportreports:read

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.

Parameters

yearquerynumber

Balance year (defaults to the current year).

min_untaken_daysquerynumber

Only employees with at least this many untaken days.

policyquerystring

Leave policy name filter (defaults to annual policies).

Request
curl "https://kumohr.com/api/v1/reports/untaken-leave" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN"
Response
{
  "data": {
    "year": 2026,
    "employees": [
      {
        "employee": "Amara Okafor",
        "department": "Engineering",
        "manager": "Lena Fischer",
        "allocated_days": 25,
        "used_days": 6,
        "untaken_days": 19
      }
    ],
    "totals": {
      "employees": 42,
      "untakenDays": 512
    }
  }
}
Server-Sent Events

Live progress that reconnects.

Stream /api/v1/agent/runs/{id}/events. Kumo sends standard SSE ids so a dropped client can continue from its final durable event.

Connect
curl -N "https://kumohr.com/api/v1/agent/runs/RUN_ID/events?cursor=18201" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN"
Events
event: status
data: {"status":"running","requestId":"req_..."}

id: 18202
event: agent.event
data: {"id":"18202","type":"step_started","payload":{"title":"Read upcoming starters"}}

event: heartbeat
data: {"cursor":"18202"}

event: done
data: {"cursor":"18209"}
statusCurrent persisted run status
agent.eventPlan, tool, action, artifact, warning, or outcome
heartbeatConnection liveness and current cursor
doneTerminal run; close the stream
errorTransport or data-source failure
Webhooks

Durable server-to-server outcomes.

SSE is the interactive channel. Webhooks notify your backend when work needs attention or reaches a durable outcome. Delivery is signed and retried with backoff.

agent.run.completedagent.run.failedagent.run.cancelledagent.action.requiredagent.artifact.createdagent.connector.health
Signature headers
Kumo-Webhook-Id: delivery_...
Kumo-Webhook-Timestamp: 1787290200
Kumo-Webhook-Signature: v1=7dc7...

# Signed input:
HMAC_SHA256(signing_secret, timestamp + "." + raw_body)
Verify with the SDK
const valid = await verifyWebhookSignature({
  secret: process.env.KUMO_WEBHOOK_SECRET!,
  timestamp: request.headers.get("Kumo-Webhook-Timestamp")!,
  body: rawBody,
  signature: request.headers.get("Kumo-Webhook-Signature")!,
  toleranceSeconds: 300
});

if (!valid) return new Response("Invalid signature", { status: 401 });
Read the raw body once

JSON re-serialization changes bytes and invalidates the signature. Verify before parsing.

Model Context Protocol

Kumo speaks MCP both ways.

Inbound

Your agent calls Kumo

Point an MCP client at https://kumohr.com/api/mcp. Tools are filtered to the PAT's scopes and the named user's role.

  • Streamable HTTP and JSON-RPC 2.0
  • Protocol 2025-06-18 and 2025-03-26
  • Cursor, VS Code, Claude Code, and custom clients
Outbound

Kumo calls your system

Register a published HTTPS MCP server or run the Connector inside your network. Every external action remains human-confirmed.

  • Named actor, run, and action attribution
  • Stable idempotency keys and structured receipts
  • No inbound port with the Connector
MCP client config
{
  "mcpServers": {
    "kumo-hr": {
      "type": "http",
      "url": "https://kumohr.com/api/mcp",
      "headers": {
        "Authorization": "Bearer kumo_YOUR_TOKEN"
      }
    }
  }
}
Outbound Connector
KUMO_URL=https://kumohr.com \
KUMO_CONNECTOR_TOKEN=kumo_cn_... \
MCP_URL=http://127.0.0.1:8799/mcp \
npm run mcp:connector
Audit

Follow one request through everything.

Kumo correlates the credential, external session, message, model calls, plan, approvals, tools, MCP receipts, artifacts, credits, recovery, and final outcome.

Encrypted payloads

Full-fidelity business payloads use AES-256-GCM after secret redaction.

Hash-chained events

Tenant sequence, previous hash, event hash, and server signature expose tampering.

Human decisions

Plan approval, action decisions, amendments, and co-signatures are normalized records.

Signed export

Admins export a manifest and verify it through the Audit API.

Trace one run
curl "https://kumohr.com/api/v1/agent/audit?runId=RUN_ID&limit=100" \
  -H "Authorization: Bearer kumo_YOUR_TOKEN"
Errors and limits

Fail clearly and retry safely.

400Invalid request

Malformed fields, unsupported decision, or missing idempotency key.

401Unauthorized

Missing, unknown, revoked, expired, or invalid credential.

403Forbidden

Missing scope, live role denial, or admin-only operation.

404Not found

The resource does not exist or is not owned by this named user.

409Conflict

Invalid run state, duplicate in progress, or idempotency mismatch.

413File too large

The attachment exceeds the accepted upload limit.

415Unsupported media

Kumo cannot extract that attachment type.

429Rate limited

Wait for the number of seconds in Retry-After.

Error envelope
{
  "error": {
    "code": "idempotency_conflict",
    "message": "That Idempotency-Key was already used for a different request."
  },
  "requestId": "req_..."
}
Ready to integrate?

Bring your architecture.

We will map identities, system boundaries, named tools, approvals, and residency with your engineering team.

Book a technical sessionDownload OpenAPI