API
API: Admin
Compliance, confidence, workspace, team, keys, billing, MCP connections, SSO, SCIM and data handling over the API.
Run your workspace over the API.
Compliance
See Compliance Evidence. Export periods use either from and to (YYYY-MM-DD, inclusive) or days (1 to 730, default 90).
GET /v1/evidence
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:compliance_export.
Change management evidence, tamper-evident. Query from, to, days and format=csv.
The evidence endpoints need a key created by an owner, admin or auditor (the evidence.export permission). Other roles, and keys not tied to a person such as CI keys, get 403 ROLE_REQUIRED, and each refusal is written to the audit log as evidence.export.denied.
Returns a JSON (or CSV) attachment with manifest (workspace, from, to, generated_at, records, gated, emergency_changes and overdue_reviews), records and emergency_changes. Records carry policy_source when the gate decision recorded one. With Close the loop on (Beta, flag close_the_loop), the export also has closed_loop (each item's id, kind, repository, title, status, routed_to, fix_url, verified_by, verified_sha, verified_at, created_at and steps), and the manifest gains closed_loop.
GET /v1/evidence/signed
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:signed_evidence.
A zip with evidence.json, evidence.csv, manifest.json and manifest.sig (an Ed25519 signature of manifest.json), plus governance.json and governance.csv with governance_evidence on. The manifest lists each file's SHA-256 and the signing key; fetch the public key from key_url. 503 SIGNING_UNAVAILABLE when evidence signing isn't available; contact Bumpkit support.
GET /v1/evidence/governance
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:governance_evidence.
Agent governance evidence: every agent-written change and how it was reviewed. Query as above, plus format=csv.
Returns workspace, from, to, generated_at, rule, summary and changes. Each change has check_id, checked_at, repository, pull_request, head_sha, agents, decision_id, outcome, approval_required, approvers, approvals_source, override fields, status, gaps and evidence_hash.
GET /v1/audit
Workspace audit log, newest first. Owners, admins and auditors only (the audit.read permission). Query limit: 1 to 500, default 100. Returns {"events": [{id, actor, actor_email, via, action, target, created_at}]}.
GET /v1/audit/events
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:siem_streaming.
The audit stream as a signed export, for a SIEM. Query as above, plus format=csv. Needs a key created by an owner, admin or auditor (audit.read). Other roles and keys not tied to a person get 403 ROLE_REQUIRED, audited as audit.read.denied. Up to 50,000 events, or 400 EXPORT_TOO_LARGE.
Returns JSON Lines (application/x-ndjson) or CSV. Each event has id, sequence, workspace_id, type, source_id, occurred_at, actor (email, via), action, target and data. The response headers sign the body:
| Header | Value |
|---|---|
X-Bumpkit-Signature |
Base64 Ed25519 signature of the body |
X-Bumpkit-Key-Id |
The signing key |
X-Bumpkit-Content-Sha256 |
Hex SHA-256 of the body |
X-Bumpkit-Events |
Number of events |
Audit streaming and auditor links
Beta, early access. Flags:
siem_streamingfor destinations,auditor_accessfor links. Destinations needintegrations.manage; links needworkspace.manage. Responses carryCache-Control: no-store.
| Method | Route | Result |
|---|---|---|
| GET | /v1/audit/streaming/sinks |
{"sinks": [...]}: id, kind, name, endpoint, enabled, pending, dead_letters, last_delivered_at and has_delivery_error |
| POST | /v1/audit/streaming/sinks |
Send kind, name, url, secret and config. Returns 201 {"id"} |
| POST | /v1/audit/streaming/sinks/{id}/test |
Sends a test event. Returns 204, or 502 DELIVERY_FAILED when the destination refuses it |
| POST | /v1/audit/streaming/sinks/{id}/enable |
Resumes delivery. Returns 204 |
| POST | /v1/audit/streaming/sinks/{id}/disable |
Pauses delivery. Returns 204 |
| DELETE | /v1/audit/streaming/sinks/{id} |
Removes the destination. Returns 204 |
| GET | /v1/audit/streaming/dead-letters |
{"dead_letters": [{id, sink_id, events, created_at}]} |
| POST | /v1/audit/streaming/dead-letters/{id}/redeliver |
Sends a failed batch again. Returns 204, or 502 DELIVERY_FAILED |
| GET | /v1/auditor-links |
{"links": [...]}: id, label, created_by, expires_at, revoked_at, last_used_at and created_at |
| POST | /v1/auditor-links |
Send label and days. Returns the link with its url, once |
| DELETE | /v1/auditor-links/{id} |
Revokes the link. Returns 204 |
See Compliance for destination kinds and settings.
GET /.well-known/bumpkit-evidence-keys/{id}
Beta, early access. Flag:
signed_evidence.
Public evidence signing key. No API key needed; limited to 60 requests per minute per IP. Returns key_id, algorithm, public_key, scope, created_at and retired_at. 404 KEY_NOT_FOUND for an unknown key.
Confidence & leadership
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flags:confidence_score,leadership_dashboards.
See Confidence Score & Leadership. The per-release score is GET /v1/checks/{id}/confidence.
GET /v1/risk
Flag confidence_score. Where releases fail most.
| Query | Description |
|---|---|
repository |
Filter |
scope |
repository, area or file (default) |
limit |
1 to 500, default 50 |
Returns {"risk": [{repository, scope, path, changes, failures, risk}]}.
GET /v1/reports/leadership
Flag leadership_dashboards. Release outcomes for leadership.
| Query | Description |
|---|---|
from, to |
YYYY-MM-DD, together. Otherwise days. |
days |
1 to 730, default 90 |
repository, team |
Filters |
format |
csv for a CSV attachment |
Returns from, to, repository, team, totals (releases, shipped, blocked, needs_approval, overridden, failed, incidents, avg_confidence, avg_risk), authorship (agent and human releases, lines and incidents, shares, and matrix: writers, committers ([{committer, person, releases, lines, cells}], each cell {writer, releases, lines, shipped, blocked, ship_rate}), totals, people_lines, people_agent_lines, people_agent_share and outcomes: per writer, releases, passed, needs_approval, blocked, pass_rate, approval_rate and blocked_rate; and coverage, as in GET /v1/reports/authorship-coverage), trend ([{week, releases, avg_confidence, avg_risk}]), repositories and teams.
GET /v1/reports/authorship-coverage
Flag leadership_dashboards. How many of your releases have verified authorship. See Authorship coverage.
| Query | Description |
|---|---|
from, to |
YYYY-MM-DD, together. Otherwise days. |
days |
1 to 730, default 90 |
repository |
One repository; omit for every repository |
Returns from, to, repository and coverage (releases, verified, inferred_only, no_signals, instrumented, headline and trend: [{week, releases, verified, inferred_only, no_signals}]).
GET /v1/reports/readiness
Flag leadership_dashboards. The release readiness report. See Release readiness report.
| Query | Description |
|---|---|
from, to |
YYYY-MM-DD, together. Otherwise days. |
days |
1 to 730, default 90 |
repository |
One repository; omit for every repository |
format |
json (default), csv or pdf. CSV and PDF come back as attachments. Anything else is 400 VALIDATION_ERROR. |
Returns title, repository, from, to, generated_at, verdict (status: ready, conditions, hold or no_releases; label and text), messages ([{text}]), releases (counts and rows), reasons (rows of {rule, outcome, status, releases, example}), authorship (writers and committers, each {name, role, releases, commits}, and coverage: {title, releases, verified, inferred_only, no_signals, instrumented}), findings (high, medium, low, info and top), approvals (requested, approved, waiting, closed, median_minutes, p90_minutes, longest_minutes and slowest). Each section has a title.
GET /v1/confidence/overview
Flag: confidence_score. How accurate scores have been, and the riskiest files and areas. Needs a key tied to a person. Query repository and days. Returns workspace_id, repository, model, files, areas, recent, file_limit, area_limit, recent_limit, recent_scope and, with the feedback flag, feedback. Use bumpkit report confidence status or the report_confidence_status MCP tool.
Workspace & team
GET /v1/overview
This workspace's release activity for the current period. Needs a key tied to a person. Returns workspace_id, period_start, period_end, as_of, activity (checks, runs, passed, needs_approval, blocked, not_checked, repositories), recent, decisions, recent_limit, repositories, private_repositories, people and, with the explanations flag, onboarding. Use bumpkit status or the status MCP tool.
GET /v1/account/github
Whether your Bumpkit login is linked to a GitHub account. Needs a key tied to a person. Returns linked, login, message and link_url. Use bumpkit account link-github or the github_link_status MCP tool.
POST /v1/features/{name}/request
Asks for early access to a Beta feature. Read-only roles get 403 FORBIDDEN. Returns {"key", "status", "created"}: status is requested, or enabled (with no created) when your workspace already has it. An unknown feature, or one that isn't in early access, answers 404 NOT_FOUND, and too many requests answer 429 RATE_LIMIT_EXCEEDED. Use bumpkit features request FEATURE or the features_request MCP tool.
GET /v1/onboarding
The first-run checklist. Needs a key tied to a person. Returns workspace_id, workspace_name, workspace_confirmed, github_app_installed, release_decision_received, dismissed, can_confirm and can_dismiss. Use bumpkit onboarding view or the onboarding_view MCP tool.
POST /v1/onboarding/workspace
Confirms the workspace name. Owners and admins only. Send workspace_id, which must match the key's workspace, and name (up to 64 characters). Returns the checklist. Use bumpkit onboarding confirm or the onboarding_confirm MCP tool.
POST /v1/onboarding/dismiss
Flag: explanations. Dismisses the checklist. Owners and admins only. Send workspace_id, which must match the key's workspace. Returns 204. Use bumpkit onboarding dismiss or the onboarding_dismiss MCP tool.
GET /v1/me
The key's identity: workspace_id, workspace_name, plan, key_label, key_prefix and user_email.
POST /v1/me/revoke
Revokes the key making the request. Returns {"revoked": true}. bumpkit logout uses it.
GET /v1/workspaces
Needs a key tied to a person. Returns {"workspaces": [{workspace_id, name, role, current}]}: every workspace that person belongs to. current is true for the workspace the key is bound to.
POST /v1/workspaces
Creates a workspace owned by the key's person. Any role in the key's workspace can do it. The new workspace gets its own team, repositories, audit log and monthly free credits.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Workspace name, up to 64 characters |
Returns 201 {"workspace_id", "name", "role": "owner", "current": false}. The key stays bound to its own workspace, so later requests still act there. To use the new workspace from the CLI, run bumpkit login and choose it. 400 VALIDATION_ERROR if the name is empty, longer than 64 characters or has unprintable characters. Each person can create up to 10 workspaces in 24 hours; past that you get 429 RATE_LIMIT_EXCEEDED with a Retry-After header. The new workspace's audit log records it as workspace.create.
DELETE /v1/workspace
Owners only, signed in to the dashboard: an API key gets 403 HUMAN_APPROVAL_REQUIRED with the link. Send workspace_id, the exact name and confirmed: true. Deletes the workspace and everything in it. Returns 204, or 400 when the name doesn't match.
GET /v1/team
Needs a key tied to a person. Returns members ([{id, email, role, created_at}]) and invitations ([{id, email, expires_at, created_at}]). With roles on, members also have active and invitations role.
POST /v1/team/invitations
Emails someone an invitation. Owner only (with roles: team.manage). Workspaces can invite unlimited teammates. Existing Bumpkit accounts can join additional workspaces without creating another account. An API key can invite as member or viewer; any higher role needs a person in the dashboard, and so does an invitation when Bumpkit can't send email.
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | Who to invite |
role |
string | No | Beta, flag roles. Default member. |
Returns 201 {"email", "role", "emailed"}. An API key never gets an invitation link: 403 HUMAN_APPROVAL_REQUIRED for what needs a person, 502 when the email couldn't be sent (cancel it and invite again). 409 CONFLICT if they're already a member or invited.
DELETE /v1/team/invitations/{id}
Owner only (with roles: team.manage). Returns 204, or 404 NOT_FOUND.
DELETE /v1/team/members/{id}
Owner only (with roles: team.manage). You can't remove yourself. The member stays out of first sign-in and IdP-managed access until you invite them again or provision them through SCIM. Returns 204, or 404 NOT_FOUND.
PATCH /v1/team/members/{id}
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:roles.
Changes a member's role. Needs roles.manage (owners and admins). Only an owner can make someone an owner or change an owner's role, and you can't change your own role.
| Field | Type | Required | Description |
|---|---|---|---|
role |
string | Yes | owner, org_admin, policy_admin, approver, member, viewer or auditor |
Returns 204. Moving someone to viewer or auditor revokes their API keys.
GET /v1/settings
Needs a key tied to a person. Returns name, plan, changelog (public, slug, title, repository, url) and memory_approval. With grouped releases on, it also returns draft_after_merge and publish_audiences, the audience whose notes each publish target gets. With CVE exposure on, it also returns vulnerability_alerts and auto_fix_prs.
PATCH /v1/settings
Owner only (with roles: workspace.manage). Send any of:
| Field | Type | Description |
|---|---|---|
name |
string | Workspace name, up to 64 characters |
changelog.public |
boolean | Publish the changelog page |
changelog.slug |
string | 3 to 40 lowercase letters, numbers and hyphens. Required to publish. |
changelog.title |
string | Page title |
changelog.repository |
string | Repository the page covers |
memory_approval |
boolean | Beta, flags codebase_memory and memory_approval. Require approval for agent memories. |
draft_after_merge |
boolean | Beta, flag grouped_releases. Draft a grouped release after every merge to the default branch. On by default. 400 while grouped releases are off. |
publish_audiences |
object | Beta, flag grouped_releases. Target to audience, e.g. {"slack": "support"}. Targets: changelog, github_release, slack, discord, notion, confluence. Defaults: customer for changelog and github_release, engineering for the rest. An empty audience resets a target to its default. Audited as settings.publish_audiences. |
vulnerability_alerts |
string | Beta, flag code_index. Which new advisories alert: all (default), reachable, critical_high or off. See Vulnerability alerts. |
auto_fix_prs |
string | Beta, flag code_index. Open fix pull requests automatically for off (default), critical or critical_high. |
Returns the settings. 409 CONFLICT if the slug is taken.
Keys & billing
GET /v1/keys
Needs a key tied to a person. Returns {"keys": [{id, prefix, label, revoked, created_at, last_used_at, expires_at}]}.
POST /v1/keys
Creates a key. Needs a key tied to a person (with roles: keys.manage, which viewers and auditors don't have).
| Field | Type | Required | Description |
|---|---|---|---|
label |
string | Yes | Up to 64 characters |
expires_at |
string | No | RFC 3339, in the future |
Returns 201 with the key's fields plus key, the full key. It is shown only here.
DELETE /v1/keys/{id}
Deletes a key. You can delete a key you created; owners and admins can delete any key in the workspace. Returns 204, 403 FORBIDDEN for anyone else, with the refusal in the audit log as key.delete.denied, or 404 NOT_FOUND.
GET /v1/billing
Returns workspace usage: private_repos_gated, people, the operational per_minute_limit, period_ends and repositories. Repositories and teammates are unlimited. For credits, use GET /v1/billing/usage.
GET /v1/billing/usage
Owners and admins. Credits for one billing period. Query period: YYYY-MM, UTC, not in the future; default the current month. Returns period, period_start, period_end, current, pricing (unit, price_per_check_cents, free_checks_per_month, estimates, purchasing_enabled), summary (credits_used, free_credits_used, free_credits_remaining, paid_credits, free_reruns and, with estimates on, estimated_charge_cents), by_repository, by_source, by_outcome and by_actor (each [{key, label, kind, credits, share, paid_credits, free_reruns, estimated_charge_cents}]) and daily ([{date, credits, free_reruns}]).
Free credits are used in time order: the period's first 60 checks are free and the rest are paid. Free re-runs are replayed decisions and never use a credit. In by_outcome, not_checked is labeled "Checked, no gate decision": A release check that ran without a release gate decision, for example from the CLI or API. It uses a credit like any other check. In by_actor, label names the real source: CLI · <host> for a CLI login, API key · <name> (or API key · <prefix>… when the key has a placeholder name), MCP · <client or agent>, GitHub App · automatic on pull requests, an agent's name or a person. Others get 403 FORBIDDEN. The dashboard's Usage and billing page, bumpkit billing usage and the get_billing_usage MCP tool show these exact numbers.
GET /v1/billing/usage/checks
Owners and admins. The period's checks and free re-runs, newest first, 25 a page. Query period and page. Returns period, page, per_page, total and events ([{id, at, check_id, repository, pull_request, head_sha, head_ref, source, source_label, outcome, outcome_label, actor, actor_kind, charge, estimated_charge_cents}]). charge is free, paid or free_rerun.
POST /v1/billing/usage/export
Owners and admins. The period's billable checks as CSV, oldest first: time_utc, check_id, repository, pull_request, head_sha, source, outcome, triggered_by, triggered_by_kind, credits, charge and, with estimates on, estimated_charge_usd. Query period. Each export is written to the audit log as billing.export. More than 100,000 checks returns 400 EXPORT_TOO_LARGE.
POST /v1/billing/portal
Owner only. Returns {"url"}, the Stripe billing portal.
MCP connections
Apps connected through the hosted MCP connector. See MCP Server.
GET /v1/mcp/connect
How to connect Claude, Codex or Grok. Works with any key. Returns url, apps, and the setup steps and commands for each app. Use bumpkit mcp connect or the mcp_connect MCP tool.
GET /v1/mcp/connections
Needs a key tied to a person. Returns {"connections": [{id, client, workspace_id, workspace, user_id, user, created_at, last_used_at}]}. Use bumpkit mcp connections list or the mcp_connections_list MCP tool.
DELETE /v1/mcp/connections/{id}
Revokes a connection, so the app must sign in again. Owners and admins can revoke anyone's; other members revoke their own, and read-only roles get 403 ROLE_REQUIRED. Returns {"revoked": true}, or 404 NOT_FOUND. Use bumpkit mcp connections revoke or the mcp_connections_revoke MCP tool.
SSO & SCIM
Beta, early access. Flags:
sso,scim,roles. Withoutroles,PATCH /v1/team/members/{id}answers403 FEATURE_EARLY_ACCESSwith a link to request access; SCIM answers401.
See SSO, SCIM & Roles. SSO sign-in runs on the dashboard. Configure it there or with the identity endpoints below.
Roles
With the roles flag on, each workspace action needs a permission:
| Role | Permissions |
|---|---|
owner |
Everything |
org_admin |
Everything except deleting the workspace and managing billing |
policy_admin |
gate.override, gate.review, policy.manage, keys.manage, incident.resolve, write |
approver |
gate.review, keys.manage, incident.resolve, write |
member |
keys.manage, incident.resolve, write |
viewer |
Read only |
auditor |
audit.read, evidence.export |
Endpoints that say "owner only" accept owners and admins, or the specific permission named. Endpoints that say "needs an owner" accept owners only. Change roles with PATCH /v1/team/members/{id}.
SCIM 2.0
Base URL: https://bumpkit.dev/scim/v2
Authenticate with a SCIM token as a bearer token:
curl https://bumpkit.dev/scim/v2/Users -H "Authorization: Bearer bk_scim_..."Owners and admins create SCIM tokens in the dashboard or with POST /v1/identity/scim/tokens. A token is shown once and stored as a hash. A missing or wrong token, or a workspace with scim off, gets 401.
Responses are application/scim+json. Errors use the SCIM error shape: {"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"], "status": "400", "detail": "...", "scimType": "invalidValue"}.
| Method | Path | Notes |
|---|---|---|
| GET | /scim/v2/ServiceProviderConfig |
PATCH and filter supported; bulk, sort, etag and change password not |
| GET | /scim/v2/ResourceTypes |
User, Group |
| GET | /scim/v2/Schemas |
User and Group schemas |
| GET | /scim/v2/Users |
Filter userName eq "x", emails.value eq "x" or externalId eq "x" |
| POST | /scim/v2/Users |
201 with Location |
| GET | /scim/v2/Users/{id} |
|
| PUT | /scim/v2/Users/{id} |
Replaces the user; the role is kept |
| PATCH | /scim/v2/Users/{id} |
add, replace, remove on active, userName, externalId, displayName |
| DELETE | /scim/v2/Users/{id} |
Deactivates the user and revokes their API keys. 204. |
| GET | /scim/v2/Groups |
Filter displayName eq "x" |
| POST | /scim/v2/Groups |
displayName (required), members. 201 with Location. |
| GET | /scim/v2/Groups/{id} |
|
| PUT | /scim/v2/Groups/{id} |
Replaces name, externalId and members |
| PATCH | /scim/v2/Groups/{id} |
members add, replace, remove (with members[value eq "id"]), displayName |
| DELETE | /scim/v2/Groups/{id} |
204. Members' roles are re-synced. |
Lists take startIndex (from 1) and count (default 100, maximum 200) and return a SCIM ListResponse.
User rules:
userNameis the email. Its domain must be verified for the workspace.- A new user gets the SSO connection's default role, or
member. There's no member limit. - Owners can't be deactivated over SCIM.
- Map groups to roles in the dashboard. When a mapped group's members change, their roles are recomputed; the highest mapped role wins. Owners are never changed.
Rate limits: 10 requests per second per token (burst 100, Retry-After: 1), and 20 failed requests per minute per IP (Retry-After: 60).
Data handling
Beta, early access. Flags:
zero_retention,regional_hosting. Withoutzero_retention, these endpoints answer403 FEATURE_EARLY_ACCESSwith a link to request access.
See Data Handling. These endpoints need a key tied to a person. Changes are owner only.
GET /v1/data
How the workspace's data is handled. Returns data_retention (standard, findings_only or ephemeral), label, description, request_log_days, findings_days (0 means forever), region, server_region, regions, region_bound, not_region_bound and stored ([{name, count, contains, code}], what the workspace keeps).
PATCH /v1/data
Owner only. Send at least one of:
| Field | Type | Description |
|---|---|---|
data_retention |
string | standard, findings_only or ephemeral. Leaving standard scrubs stored code right away. |
request_log_days |
integer | 1 to 3650, or 0 to keep forever |
findings_days |
integer | 1 to 3650, or 0 to keep forever |
region |
string | Flag regional_hosting. Pin the workspace to the region its data is stored in (server_region), or "" to unpin. Without the flag, 403 FEATURE_DISABLED. |
Fields are applied in the order region, retention, windows, and each is saved as it goes, so an error on a later field leaves earlier ones changed. Returns the same body as GET /v1/data.
When a workspace is pinned to another region, every API request sent to another region's API fails with 421 WRONG_REGION. The response has X-Bumpkit-Region and, when known, a Location header with the right API URL.
GET /v1/data/export
Owner only. Limited to 5 per hour per workspace (Retry-After: 3600). Returns a JSON attachment bumpkit-workspace-export.json with format, exported_at, exported_by and one section for each kind of data the workspace stores. See Export workspace data.
POST /v1/data/delete
Owner only, signed in to the dashboard: an API key gets 403 HUMAN_APPROVAL_REQUIRED with the link. Permanently deletes the workspace's stored data. The workspace, its members and keys stay. A denial on a commit keeps holding that commit, with the person's name and email removed.
| Field | Type | Required | Description |
|---|---|---|---|
confirm |
string | Yes | The workspace name, exactly |
Returns {"deleted": {...}} with the number of records removed for each kind of data.
Workspace identity management
All routes below require an active, person-bound key belonging to an owner or admin of the selected workspace and the same feature access as the dashboard. Anonymous workspace keys and read-only roles cannot manage identity settings. Records are scoped to that workspace.
| Method | Route | Result |
|---|---|---|
| GET | /v1/identity/domains |
{ "domains": [...] } with ID, domain, txt_name, txt_value, verified_at, and created_at |
| POST | /v1/identity/domains |
Send { "domain": "example.com" }; returns 201 |
| POST | /v1/identity/domains/{id}/verify |
Verify the published DNS TXT record; returns 204 only after ownership is verified |
| DELETE | /v1/identity/domains/{id} |
Remove the domain; returns 204 |
| GET | /v1/identity/scim/tokens |
{ "tokens": [...] } containing ID, label, prefix, creation and last-use timestamps; no secrets |
| POST | /v1/identity/scim/tokens |
Send { "label": "Okta" }; returns 201 with { "token": "..." } exactly once |
| DELETE | /v1/identity/scim/tokens/{id} |
Revoke the token; returns 204 |
Missing or another workspace's IDs return 404. Invalid domains, labels and failed DNS verification return 400. SSO connection configuration and SCIM group-role mapping are available below.
| Method | Route | Result |
|---|---|---|
| GET | /v1/identity/sso |
Secret-free settings, saved-secret indicator, OIDC callback URL and SAML service-provider URLs |
| PUT | /v1/identity/sso |
Full settings JSON; validates OIDC discovery or SAML certificate and verified domains before enforcement; returns 204. Setting up or changing the provider, turning off or no longer requiring single sign-on, and a default role above member, need an owner signed in to the dashboard; an API key gets 403 HUMAN_APPROVAL_REQUIRED |
| DELETE | /v1/identity/sso |
Remove the workspace's provider configuration; needs an owner; returns 204 |
| POST | /v1/identity/sso/unlink |
Send {"email": "..."} to clear a member's identity provider link, so they link again on their next sign-in; clearing an owner's link needs an owner; returns 204 |
| GET | /v1/identity/scim/groups |
{ "groups": [...] } with IDs, display names and mapped roles |
| PUT | /v1/identity/scim/groups/{id}/role |
Send { "role": "viewer" }, or an empty string to clear; returns 204 after synchronizing roles |
SSO settings accept protocol, enabled, enforced, jit, default_role, issuer, client_id, client_secret, entity_id, sso_url, and certificate. Secrets are accepted only as request-body data and never included in a settings response. An omitted or empty OIDC client secret preserves the current secret. The API validates the same state transitions as the dashboard; it does not accept a caller's claim that a domain or identity provider was verified. Reading or modifying configuration does not create an SSO session or identity-provider proof. SSO routes require SSO feature access; groups require SCIM, and role mapping additionally requires the roles feature. Owner and admin permissions apply to every route.
IdP-managed MCP access
Beta, early access. Flag:
idp_managed_mcp, plussso. Until your workspace has access, these routes answer403 FEATURE_EARLY_ACCESSwith a link to request it.
Your identity provider decides who can use the MCP server, and MCP clients trade an ID-JAG for an access token with no Bumpkit sign-in. See IdP-managed MCP access. Owners and admins only; responses are never cached.
| Method | Route | Result |
|---|---|---|
| GET | /v1/identity/sso/managed-mcp |
enabled, required, tenant, role_domain, issuer, audience, resource, token_endpoint, aud_tenant (the workspace ID), scopes and clients (client_id, name, secret_prefix, created_at, last_used_at), without secrets |
| PUT | /v1/identity/sso/managed-mcp |
Replaces all four settings, so send every one you want to keep. Changing the tenant or Athenz domain, turning it off, or no longer requiring it needs an owner signed in to the dashboard; an API key gets 403 HUMAN_APPROVAL_REQUIRED. Send {"enabled": true, "required": false}, optionally with tenant (the identity provider tenant ID-JAGs must name, for multi-tenant issuers) and role_domain (the Athenz domain whose roles map to scopes); returns 204. Turning it on needs OIDC single sign-on turned on; requiring it needs it turned on and a verified domain. Turning it off works without single sign-on |
| POST | /v1/identity/sso/managed-mcp/clients |
Send {"name": "Claude"} (up to 64 characters), optionally with client_id, the ID your identity provider puts in ID-JAGs (up to 255 of A-Z a-z 0-9 . _ : / @ + ~ -; 409 if it's already registered in this workspace). Without it Bumpkit generates bkmcp_ema_.... Returns 201 with client_id, name, secret_prefix, created_at and client_secret, shown once |
| DELETE | /v1/identity/sso/managed-mcp/clients/{id} |
Remove the client and stop every token issued to it; returns 204, or 404 for an unknown client |
| POST | /v1/identity/sso/managed-mcp/test |
Send {"assertion": "<ID-JAG>"}; returns accepted, with error and hint when Bumpkit would refuse it, and what it read: issuer, client_id, subject, member, role, scope, creates_member and expires_at. The ID-JAG isn't used up |
MCP clients trade the ID-JAG at POST https://bumpkit.dev/oauth/token with grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer, assertion, and the client ID and secret by HTTP Basic or in the form. The response has access_token, token_type, expires_in (at most 3600) and scope, with no refresh token. Errors and fixes: Troubleshooting.