API
API: Agents
Agent memory, policy, telemetry, vendor usage, swarms and swarm governance over the API.
Give coding agents memory and coordinate them.
Agents & memory
See Agent Controls and Agent Hooks. Agent telemetry and AI vendor usage have their own sections below.
POST /v1/memories
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:codebase_memory.
Saves something the next person or agent working in a repository should know.
| Field | Type | Required | Description |
|---|---|---|---|
repository |
string | Yes | owner/name |
path |
string | No | The file or directory it applies to. Empty means the whole repository. |
kind |
string | No | note (default), decision, pitfall or incident |
body |
string | Yes | Up to 2000 characters |
author |
string | No | Who wrote it |
Returns 201 with the memory: id, repository, path, kind, body, author, created_at. Saving the same text again for the same repository, path and kind refreshes the existing memory instead of adding a duplicate.
With memory approval on (Beta, flag memory_approval), the memory also has status: approved, or pending until a person approves it. A memory is pending when the workspace setting memory_approval is on, or the repository's bumpkit.yml sets memory.require_approval. With the ephemeral data retention mode, saving a memory fails with 409 NOT_STORED.
GET /v1/memories
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:codebase_memory.
Recalls memories for a path, with its release history. Query repository (required) and path.
Returns repository, path, memories (the most relevant first, capped in number and total length), releases (recent checks that touched the path), flagged ([{kind, count}] finding kinds seen there) and agents. Only approved memories are recalled.
DELETE /v1/memories/{id}
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:codebase_memory.
Forgets a memory. Returns 204, or 404 MEMORY_NOT_FOUND.
GET /v1/memories/pending
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flags:codebase_memory,memory_approval.
Lists memories waiting for approval, newest first. Needs a key tied to a person. Query repository and limit (1 to 500, default 100). Returns {"memories": [Memory]}.
POST /v1/memories/{id}/approve
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flags:codebase_memory,memory_approval.
Approves a pending memory. Needs a key tied to a person. A key can't approve a memory saved with a key of the same person, or with a key that was since deleted (403 FORBIDDEN). Review those on the Approvals page in the dashboard, or with a teammate's key. Returns 200 with the memory, or 404 NOT_FOUND if it isn't pending.
POST /v1/memories/{id}/reject
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flags:codebase_memory,memory_approval.
Rejects a pending memory. Same rules as approve.
POST /v1/agent/decisions
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:agent_pause.
Records a decision an agent hook made about a command, or asks a person to decide. Limited to 240 requests per minute per key.
| Field | Type | Required | Description |
|---|---|---|---|
tool |
string | Yes | The agent tool, such as Bash |
command |
string | Yes | The command. Secrets are redacted again on the server. |
decision |
string | Yes | allow, ask or deny |
repository |
string | No | owner/name |
agent |
string | No | Agent name |
session |
string | No | Agent session |
command_hash |
string | No | SHA-256 hex of the redacted command. Computed when missing or invalid. |
rules |
string[] | No | Rule IDs that matched, such as rm_rf, force_push, sql_drop or secret_write. Unknown IDs are dropped. |
reason |
string | No | Up to 1000 characters |
remote |
boolean | No | With ask, wait for a person to approve on the dashboard's Approvals page |
timeout_seconds |
integer | No | How long a remote ask waits, 5 to 120, default 30 |
Returns 201 with id, repository, agent, session, tool, command, command_hash, rules, reason, decision, status, approver_email, expires_at, decided_at and created_at. status is pending for a remote ask, otherwise decided.
GET /v1/agent/decisions
Reads stored command decisions for the authenticated person's current workspace. Requires a person-bound API key and access to agent_pause; viewer and read-only keys can read. This endpoint does not evaluate commands or change decisions.
| Query | Description |
|---|---|
status |
recent (default) or pending |
limit |
1–500; defaults to 20 for recent or 50 for pending |
recent includes decided commands and expired requests. pending includes only unexpired pending requests. Both are ordered by creation time, newest first, matching the dashboard. Expired pending records are returned with status: "expired". Returns {"status":"recent","now":"...","decisions":[AgentDecision]}. Invalid parameters return 400 VALIDATION_ERROR.
GET /v1/agent/decisions/{id}
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:agent_pause.
Returns a decision. Poll it while status is pending; it becomes approved, denied or expired. 404 AGENT_DECISION_NOT_FOUND for an unknown ID.
POST /v1/agent/work
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:agent_guard.
Reports the branch and commits an agent session worked on, so the release gate treats them as agent-written. The Bumpkit agent hooks send this for you. Limited to 600 requests per minute per key.
| Field | Type | Required | Description |
|---|---|---|---|
agent |
string | Yes | claude-code, cursor, codex, gemini, windsurf, cline or copilot |
session_id |
string | Yes | 1 to 200 letters, digits, ., _, : or - |
repository |
string | Yes | owner/name or the remote URL |
branch |
string | For no commits | The branch the session worked on. Required, and not the default branch, when commits is empty. |
head_sha |
string | No | The full commit SHA of the branch head |
commits |
string[] | No | Up to 200 full commit SHAs the session's branch adds |
Returns 202 {"session": "<id>", "commits": n}. 403 FORBIDDEN for a viewer or a key that can't report agent work. 409 PROVENANCE_SESSION_CONFLICT when another account or key started the session.
POST /v1/provenance/events
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:change_provenance.
Records an agent session event from an agent hook. Limited to 600 requests per minute per key.
| Field | Type | Required | Description |
|---|---|---|---|
agent |
string | Yes | claude-code, cursor, codex, gemini, windsurf, cline or copilot |
session_id |
string | Yes | 1 to 200 letters, digits, ., _, : or - |
event |
string | Yes | start, tool, prompt or end |
tool |
string | For tool |
Tool name, up to 64 characters |
prompt |
string | No | On prompt events. Secrets are redacted and it is cut to 280 characters. |
agent_version, model |
string | No | The agent's version and model |
repository, branch, head_sha |
string | No | Where the agent is working |
sponsor |
string | No | Ignored. The sponsor is the API key's person, or key:<id> for a key tied to no person. |
Returns 202 {"session": "<id>", "events": n}. 403 FORBIDDEN for a viewer or a key that can't record events. 409 PROVENANCE_SESSION_CONFLICT when another account or key started the session.
GET /v1/checks/{id}/provenance
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:change_provenance.
Who and what produced a checked change. Returns workspace_id, check_id, repository, pull_request, base, head, head_sha, checked_at, decided_at, agents, sponsors, sessions, trailers, approvals, approvals_source and verification. A session's sponsor_verified is true only when it was reported with a person's key. 404 NOT_FOUND for an unknown check.
With agent forensics on (flag agent_forensics), the response also has forensics: events, each with at, kind (session, guard, check, gate or outcome), text and source (reported or recorded), and signals, each with kind and observed. Signals never block a release.
GET /v1/checks/{id}/attestation
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:change_provenance.
The provenance as an in-toto statement (predicate type https://bumpkit.dev/attestation/change-provenance/v1). Unsigned: {"check_id", "signed": false, "statement"}. Signed: {"check_id", "signed": true, "envelope"}, a DSSE envelope with an Ed25519 signature. 500 SIGNING_KEY_INVALID if attestation signing isn't working; contact Bumpkit support.
GET /v1/provenance/key
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:change_provenance.
The public key that signs attestations: {"signed": true, "keyid", "public_key", "algorithm": "ed25519"}, or {"signed": false}.
GET /v1/agent/guard-events
Beta, early access. Flag:
agent_pause.
What the agent guard did to the files of a change. Works with any key and is limited per key. Query repository and one file for each path. Without a file, events is empty.
Returns {"repository", "events": [{file, decision_id, agent, session, tool, command, decision, status, rules, direct, at, text}]}, newest first. Each event is a decision other than allow. direct is true when the decision touched file itself, and false when it came from a session that worked on file. bumpkit blast-radius and the blast_radius MCP tool read it from a checkout.
GET /v1/repositories/{owner}/{repo}/agent-hooks
Beta, early access. Flag:
agent_hooks_pr.
Whether the repository has the team agent hooks. Owners, admins and policy admins only. Returns repository, status (missing, pull_request_open or installed), branch, files and pull_request (number, url). POST /v1/repositories/{owner}/{repo}/agent-hooks opens the pull request and returns the same fields with 201 and created: true when it opened one. Use bumpkit hooks pr --repo OWNER/NAME to open it and the agent_hooks_status MCP tool to read the state.
Agent policy
Beta, early access. Flag:
org_policies.
The locked company-wide agent policy. These routes need a key tied to a person. Any role can read; only owners and admins can change it. The CLI is bumpkit agent policy show, set, history and diff; the MCP tools are agent_policy_show, agent_policy_set, agent_policy_history and agent_policy_diff.
| Method | Route | Result |
|---|---|---|
| GET | /v1/policy/agent |
The latest version: version, content, message, actor_email and created_at. 404 NOT_FOUND when the workspace has no agent policy yet |
| PUT | /v1/policy/agent |
Send content (YAML, under 64 KB) and optionally message (up to 500 characters). Returns {"policy", "diff"}, 400 VALIDATION_ERROR when the policy doesn't parse, or 409 CONFLICT when nothing changed |
| GET | /v1/policy/agent/versions |
{"versions": [...]}, newest first. Query limit: 1 to 200, default 50 |
| GET | /v1/policy/agent/versions/{version} |
One version, or 404 NOT_FOUND |
GET /v1/agent/policy
Beta, early access. Flag:
agent_pause.
The signed copy of the policy that agent hooks enforce. Works with any key and is limited per key. Returns {"payload", "signature", "key_id"}. payload is base64 JSON with workspace, version, content, issued_at and expires_at, 24 hours after it was issued. With no policy, or without org_policies, version is 0 and content is empty. 503 SIGNING_UNAVAILABLE when Bumpkit can't sign right now. bumpkit pause fetches and caches it for you.
Agent telemetry
Beta, early access. Flag:
agent_telemetry.
See Agent Telemetry. Every route needs a key created by an owner or admin; other keys get 403 FORBIDDEN. Your exporter doesn't call these: it sends events to the endpoint in the setup guide with an ingest key.
The CLI is bumpkit agents telemetry, with status, enable, disable, mode, scope, retention, identity, keys, events, purge and test. The MCP tools have the same names, such as agent_telemetry_status and agent_telemetry_keys_create.
| Method | Route | Result |
|---|---|---|
| GET | /v1/agent-telemetry |
settings, keys, stats (events, commits, matched, unmatched, match_rate, rejected, last_event_at, last_error, last_error_at), the 20 latest events, endpoint, header, paths, kept and never_stored |
| PUT | /v1/agent-telemetry/settings |
Send the fields below. Returns the saved settings |
| GET | /v1/agent-telemetry/keys |
{"keys": [{id, name, prefix, allowed_cidrs, created_at, expires_at, last_used_at, last_used_ip, events, rejected, expired}]} |
| POST | /v1/agent-telemetry/keys |
Send name (up to 64 characters), optionally expires_in_days (1 to 730) and allowed_cidrs. Returns 201 {"key", "secret", "managed_settings", "env"}. The secret is shown once |
| POST | /v1/agent-telemetry/keys/{id}/rotate |
Replaces the secret and returns the same fields. The old secret stops working |
| DELETE | /v1/agent-telemetry/keys/{id} |
Revokes the key. Returns 204, or 404 NOT_FOUND for an unknown or revoked key |
| GET | /v1/agent-telemetry/events |
{"events": [{id, received_at, name, key, session_id, user, repository, branch, commit_sha, agent, matched, matched_by}]}, newest first. Query limit: 1 to 200, default 50 |
| POST | /v1/agent-telemetry/purge |
Deletes every stored event. Returns {"purged": n} |
| POST | /v1/agent-telemetry/test |
Send secret to check an ingest key, or {} to check for events. Returns ok, message, and key and last_seen_at when known |
Settings fields:
| Field | Type | Description |
|---|---|---|
mode |
string | off, observe or enforce. Required |
scope |
string | all (default), allow or deny |
repositories |
array | owner/name values, up to 500. Required for allow and deny |
retention_days |
integer | 1, 7 (default) or 30 |
identity |
string | keep, hash (default) or drop |
alerts |
object | unused_key_days (0 to 365), ip_allowlist (boolean) and rejection_spike (0 to 100000). 0 turns an alert off |
AI vendor usage
Beta, early access. Flag:
vendor_usage.
See AI Vendor Usage. Every route needs a key created by an owner or admin; other keys get 403 FORBIDDEN. {vendor} is anthropic, claude-enterprise, cursor or copilot.
The CLI is bumpkit agents vendors, with status, connect, disconnect, sync, retention and identities. The MCP tools have the same names, such as agent_vendors_status and agent_vendors_identities_map.
| Method | Route | Result |
|---|---|---|
| GET | /v1/vendor-usage |
settings (retention_days), vendors, people and window_days |
| PUT | /v1/vendor-usage/settings |
Send retention_days: 30, 90, 180 or 365. Returns the saved settings |
| PUT | /v1/vendor-usage/vendors/{vendor} |
Send key, and org for copilot. Bumpkit tries the key against the vendor first and answers 400 VALIDATION_ERROR if the vendor refuses it. Returns the connection with connected, org, key_hint, connected_at, last_synced_at, synced_from, synced_through, rows, last_error and last_error_at |
| DELETE | /v1/vendor-usage/vendors/{vendor} |
Removes the key, the stored usage and the identity mappings. Returns 204, or 404 NOT_FOUND when it isn't connected |
| POST | /v1/vendor-usage/vendors/{vendor}/sync |
Reads the latest usage now. Returns vendor, since, until, rows and message, or 409 CONFLICT when a sync started less than a minute ago |
| GET | /v1/vendor-usage/identities |
{"identities": [{vendor, user, committer, source}]} |
| PUT | /v1/vendor-usage/identities |
Send vendor, user and committer (a GitHub login or commit email). Returns the mapping with source: "admin" |
| DELETE | /v1/vendor-usage/identities |
Query vendor and user. Returns 204, or 404 NOT_FOUND when there's no such mapping |
Swarms
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it.
Claims keep coding agents on the same repositories from colliding. The CLI and MCP server call the other swarm endpoints for you; see Agent Swarms. Claims work with any key in the workspace. Repositories are owner/name or a github.com URL.
POST /v1/claims
Flag swarm_claims. Claims a resource so other agents don't collide with it.
| Field | Type | Required | Description |
|---|---|---|---|
repository |
string | Yes | owner/name |
kind |
string | Yes | migration, path, symbol, route, flag, env or other |
resource |
string | Yes | Up to 300 characters. A migration is its number (48); a route is METHOD path. |
agent |
string | Yes | Who holds the lease, up to 100 characters |
session |
string | Yes | Which run of it, up to 100 characters |
note |
string | No | Up to 500 characters |
ttl_seconds |
integer | No | Lease length, clamped to 60 seconds to 24 hours. Default 1800. |
Returns 201 with the claim: id, repository, kind, resource, agent, session, sponsor, note, created_at, renewed_at, expires_at, released_at. Claiming again with the same agent and session renews it.
When another agent holds the resource, the response is 409 with a different shape:
{
"status": "error",
"error": {
"code": "CLAIM_HELD",
"message": "migration 48 is held by codex (session s-2) until 2026-10-22T15:04:05Z.",
"suggestion": "Claim 49 instead, or wait for the lease to expire."
},
"holder": { "id": "...", "kind": "migration", "resource": "48", "agent": "codex" },
"alternative": "49"
}GET /v1/claims
Flag swarm_claims. Active claims. Query repository, kind, agent and limit (default 100, maximum 500). Returns {"claims": [Claim]}.
POST /v1/claims/migration
Flag swarm_claims. Claims the next free migration number.
| Field | Type | Required | Description |
|---|---|---|---|
repository, agent, session |
string | Yes | As for claims |
dir |
string | No | Migrations directory, default db/migrations |
known |
integer[] | No | Numbers you already see locally |
note |
string | No | Claim note |
ttl_seconds |
integer | No | Default 24 hours |
Bumpkit claims the next number nobody is using, here or in open pull requests. Returns 201 {"number": 49, "name": "049", "claim": Claim, "taken": {...}}.
POST /v1/claims/{id}/renew
Flag swarm_claims. Send agent, session (must match the holder) and optionally ttl_seconds. Returns 200 with the claim. 404 CLAIM_NOT_FOUND, 410 CLAIM_RELEASED, or 403 FORBIDDEN when you aren't the holder.
POST /v1/claims/{id}/release
Flag swarm_claims. Same body as renew. A key created by a workspace owner or admin can release anyone's claim; other keys get 403 FORBIDDEN, audited as claim.release.denied. Bumpkit records who forced the release. Returns 200 with the claim, released_at set. 410 CLAIM_RELEASED if already released.
GET /v1/swarm
Flags: swarm_claims, conflict_prediction or merge_planning. Stored coordination state, read without recomputing. Needs a key tied to a person. Returns workspace_id, claims, intents, plans, claims_limit, intents_limit and plans_limit. Use bumpkit swarm status or the swarm_status MCP tool.
GET /v1/merge-plans
Flag: merge_planning. Stored merge plans, ordered by repository. Needs a key tied to a person. Returns workspace_id, plans, limit and order. Use bumpkit merge-plans or the merge_plans MCP tool.
Test database leases
Flag: test_isolation. Tracks the test databases your agents lease. Works with any key and is limited per key. bumpkit testdb creates and drops the databases and calls these for you; the MCP tools are test_database_lease, test_database_release, testdb_list and testdb_sweep.
| Method | Route | Result |
|---|---|---|
| POST | /v1/testdb/leases |
Send name (starts with bk_lease_), host (host[:port]), and optionally agent and ttl_seconds (60 to 86400, default 3600). Returns 201 with id, name, host, agent, expires_at and created_at |
| GET | /v1/testdb/leases |
{"leases": [...]} |
| DELETE | /v1/testdb/leases |
Query host and name. Returns 204 |
Swarm governance
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it.
Rules agents learn from, and history they check before they build. See Agent Swarms. Each endpoint names its flag. Proposing and searching work with any key in the workspace; reviewing lessons needs a key tied to a person.
POST /v1/lessons
Flag swarm_lessons. Proposes a lesson: a repository-wide rule that any agent can propose and only a person can approve.
| Field | Type | Required | Description |
|---|---|---|---|
repository |
string | Yes | owner/name |
body |
string | Yes | The rule, up to 1000 characters |
kind |
string | No | practice (default), pitfall, decision, or dropped for something the team chose not to build |
paths |
string[] | No | Up to 20 paths it applies to. Empty means the whole repository. |
areas |
string[] | No | Any of tests, migrations, auth, api, ui, authentication, authorization, billing, cryptography |
proposed_by |
string | No | Who proposed it, such as the agent id |
supersedes |
string | No | The id of a lesson this replaces. The new one becomes the next version in the same lineage, and approving it supersedes the old one. |
Returns 201 with the lesson: id, repository, lineage_id, version, kind, body, paths, areas, status (pending), proposed_by, supersedes, reviewed_by, reviewed_at, retired_by, retired_at, retire_reason and created_at. Proposing the same text again for the same repository returns the existing lesson. 404 LESSON_NOT_FOUND when supersedes names an unknown lesson.
GET /v1/lessons
Flag swarm_lessons. Query repository, path, area and status (approved by default, or pending, retired, superseded, rejected or all). Returns {"lessons": [Lesson]}, up to 200.
GET /v1/memories also returns the approved lessons for the path when the flag is on. Pending, rejected and retired lessons never reach agents.
POST /v1/lessons/{id}/approve
Flag swarm_lessons. Approves a pending lesson. Needs a key tied to a person. A key can't approve a lesson proposed with a key of the same person, or with a key that was since deleted (403 FORBIDDEN). Review those in the dashboard inbox, or with a teammate's key. Returns 200 with the lesson. 404 NOT_FOUND if no pending lesson has that id. Audited as lesson.approve.
POST /v1/lessons/{id}/reject
Flag swarm_lessons. Rejects a pending lesson. Same rules as approve; audited as lesson.reject.
POST /v1/lessons/{id}/retire
Flag swarm_lessons. Retires an approved lesson. Needs a key tied to a person. Send {"reason": "..."}, 10 to 500 characters. Returns 200 with the lesson, or 404 NOT_FOUND. Audited as lesson.retire.
POST /v1/tried
Flag tried_before. Searches release history before you build something: reverted commits, files that were added and later deleted, removed APIs and breaking changes, decision and dropped lessons, and past gate blocks.
| Field | Type | Required | Description |
|---|---|---|---|
query |
string | One of | A few words describing the change |
paths |
string[] | One of | Paths it touches, up to 10 |
symbols |
string[] | One of | Symbols it touches |
repository |
string | No | owner/name. Omit to search every repository. |
Returns 200 {"query", "tried", "summary", "evidence"}. Each evidence item has kind (revert, removed_file, removed_feature, removed_api, decision, dropped_decision, gate_block or release), title, detail, repository, check_id, commit, link (the release page), commit_link (GitHub repositories), score and at. 400 VALIDATION_ERROR when there is nothing to search for. With the findings_only and ephemeral data retention modes, commit subjects aren't stored, so fewer matches are found.