Management API
Beyond chatting, a scoped key can create and configure resources: agents, knowledge sets, models, tasks, teams, webhooks and schedules. This is what you use to provision BasePeak.AI from code rather than clicking through the admin UI.
The OpenAPI spec is the reference
Every instance serves its own machine-readable spec, and it is generated from the same table that drives route registration — so it cannot drift from what the server actually exposes:
curl -sS https://your-instance.platform.basepeak.ai/api/openapi.json
curl -sS https://your-instance.platform.basepeak.ai/api/openapi.yaml
Both are reachable without authentication. Prefer them over any table in these docs when the two disagree on request or response shape: the spec is generated, the prose is written by hand.
The spec covers everything an API key can reach, not just the management
routes on this page. Operations are grouped by surface (tags):
| Tag | What it covers | Page |
|---|---|---|
Chat | Invoke API: send a turn to an agent | Invoke API |
OpenAI | OpenAI-compatible routes under /v1 | OpenAI-compatible API |
Threads | List and read conversations, replay events, cancel a run | Threads |
Files | Workspace files on an agent and on a conversation | Files |
Projects | Project-addressable chat, workspace, knowledge, environment, tasks | Projects |
Management | The catalogue: agents, knowledge sets, models, tools, tasks, teams, triggers | this page |
Key creation (/api/account/apikeys) is deliberately absent: it is bound
to a signed-in session and rejects API keys, so including it would document a
guaranteed 403. Keys are created in the UI — see
API keys.
Each operation carries an x-required-scope extension naming the scope it
needs — admin means no key can reach it.
Two route spellings are intentionally not in the spec:
/api/invoke/{id}/thread/{thread} (singular) and the /file/ variants of the
file routes. They still work, but they are equivalent legacy forms of the
documented plural spelling; listing both would double every generated client
without adding a single capability.
Generating a typed client is the intended workflow:
# Python
openapi-python-client generate --url https://your-instance.platform.basepeak.ai/api/openapi.json
# TypeScript
npx openapi-typescript https://your-instance.platform.basepeak.ai/api/openapi.json -o bpai.d.ts
# Go
oapi-codegen -package bpai <(curl -sS https://your-instance.platform.basepeak.ai/api/openapi.yaml) > bpai.gen.go
Management scopes
Nine management permissions can be minted into a key. Each is a
resource:action pair used as the first two segments of a scope:
| Scope | Grants |
|---|---|
agent:create:* | Create, list, read, copy, export and import agents |
agent:update:* | Modify agents: manifest, default flag, knowledge-set attach/detach, authorizations |
agent:delete:* | Delete agents |
knowledgeset:manage:* | Full knowledge-set lifecycle, files, imports and exports |
tool-reference:manage:* | Register, update, delete and refresh tools and MCP servers |
model-provider:manage:* | Manage models, and configure or validate model providers |
trigger:manage:* | Webhooks, email receivers and cronjobs |
task:manage:* | Tasks and task runs |
team:manage:* | Agent teams |
Management scopes must use * in the id segment — with one exception,
below. Minting a key still requires that you currently hold the
underlying permission, so a key can never grant more than its creator has.
Grounding a key to a single agent
agent:update is the only management permission that accepts a concrete id
instead of *:
| Scope | Reach |
|---|---|
agent:update:* | May update any agent its owner can |
agent:update:a17jlm7 | May update only agent a17jlm7 |
Every agent:update route carries the agent as its first path parameter,
so the grounded id is enforced per request — a grounded key gets 403 on
any other agent.
This exists for the self-improving-agent case: an agent that rewrites its own instructions should hold a key that can modify itself and nothing else.
{
"name": "self-improve",
"scopes": ["agent:chat:a17jlm7", "agent:update:a17jlm7"]
}
A key may carry several scopes; there is no one-scope limit.
The route catalogue
The scoped-key management surface, grouped by resource. {…} are path
parameters.
Agents
| Method | Path | Scope |
|---|---|---|
POST | /api/agents | agent:create |
GET | /api/agents | agent:create |
GET | /api/agents/{id} | agent:create |
PUT | /api/agents/{id} | agent:update |
DELETE | /api/agents/{id} | agent:delete |
POST | /api/agents/{id}/copy | agent:create |
GET | /api/agents/{id}/export | agent:create |
POST | /api/agents/import | agent:create |
PUT | /api/agents/{id}/setdefault | agent:update |
POST | /api/agents/{id}/knowledge-sets/{knowledge_set_id}/attach | agent:update |
DELETE | /api/agents/{id}/knowledge-sets/{knowledge_set_id}/detach | agent:update |
GET | /api/agents/{id}/authorizations | agent:create |
POST | /api/agents/{id}/authorizations/add | agent:update |
POST | /api/agents/{id}/authorizations/remove | agent:update |
Export/import use a YAML-or-JSON agent envelope, so an agent can be moved between instances as a file.
Knowledge sets
| Method | Path | Scope |
|---|---|---|
POST GET | /api/knowledge-sets | knowledgeset:manage |
GET PUT DELETE | /api/knowledge-sets/{id} | knowledgeset:manage |
GET | /api/knowledge-sets/{id}/knowledge-files | knowledgeset:manage |
POST DELETE | /api/knowledge-sets/{id}/knowledge-files/{file...} | knowledgeset:manage |
POST GET | /api/knowledge-sets/{id}/exports | knowledgeset:manage |
GET DELETE | /api/knowledge-sets/{id}/exports/{export_id} | knowledgeset:manage |
POST GET | /api/knowledge-set-imports | knowledgeset:manage |
GET DELETE | /api/knowledge-set-imports/{import_id} | knowledgeset:manage |
Models and providers
| Method | Path | Scope |
|---|---|---|
POST | /api/models | model-provider:manage |
PUT DELETE | /api/models/{id} | model-provider:manage |
GET | /api/models, /api/models/{id} | admin-only |
GET | /api/model-providers | model-provider:manage |
GET | /api/model-providers/{model_provider_id} | model-provider:manage |
POST | /api/model-providers/{id}/configure | model-provider:manage |
POST | /api/model-providers/{id}/validate | model-provider:manage |
configure and validate take a flat environment-variable map as their
body.
Tools and MCP servers
| Method | Path | Scope |
|---|---|---|
POST | /api/tool-references | tool-reference:manage |
PUT DELETE | /api/tool-references/{id} | tool-reference:manage |
POST | /api/tool-references/{id}/force-refresh | tool-reference:manage |
POST | /api/tool-references/test-mcp | tool-reference:manage |
GET | /api/tool-references | no token required (public) |
GET | /api/tool-references/{id} | admin-only |
Registering a remote MCP server is a tool-references create — MCP servers
are modelled as tools rather than as a separate resource.
POST /api/tool-references/test-mcp probes a candidate server before you
save it. Send {"url": "https://…"}; it replies with reachable,
authRequired, dcrSupported and a detail string, so a provisioning script
can fail fast on an unreachable endpoint.
Tasks
| Method | Path | Scope |
|---|---|---|
GET | /api/tasks | task:manage |
GET PUT DELETE | /api/tasks/{id} | task:manage |
POST | /api/tasks/{id}/run | task:manage |
GET | /api/tasks/{id}/runs | task:manage |
GET DELETE | /api/tasks/{id}/runs/{run_id} | task:manage |
A task:manage key sees only its owner's tasks; the all-tasks view is
an admin-session feature. POST /{id}/run takes free-form JSON as input
({} for none) and returns the run — useful for triggering an existing
task from CI.
Teams
| Method | Path | Scope |
|---|---|---|
GET POST | /api/teams | team:manage |
GET PUT DELETE | /api/teams/{id} | team:manage |
Teams are workspace-global, so a team:manage key manages every team. The
team chat routes are a separate end-user surface and are not part of
the management API.
Triggers
| Method | Path | Scope |
|---|---|---|
POST GET | /api/webhooks | trigger:manage |
GET PUT DELETE | /api/webhooks/{id} | trigger:manage |
POST GET | /api/email-receivers | trigger:manage |
GET PUT DELETE | /api/email-receivers/{id} | trigger:manage |
POST GET | /api/cronjobs | trigger:manage |
GET PUT DELETE | /api/cronjobs/{id} | trigger:manage |
Webhook create/update accept a write-only token field alongside the
manifest; it is never returned on read.
Example: provision an agent end to end
With a key holding agent:create:*, agent:update:*,
knowledgeset:manage:* and agent:chat:*:
import httpx, pathlib
api = httpx.Client(
base_url="https://your-instance.platform.basepeak.ai",
headers={"Authorization": f"Bearer {TOKEN}"},
timeout=60,
)
# 1. Create the agent.
agent = api.post("/api/agents", json={
"name": "Support Assistant",
"description": "Answers questions from the support handbook",
"prompt": "You are a support assistant. Answer only from your knowledge.",
}).raise_for_status().json()
agent_id = agent["id"]
# 2. Create a knowledge set.
ks = api.post("/api/knowledge-sets", json={
"name": "Support handbook",
}).raise_for_status().json()
ks_id = ks["id"]
# 3. Upload documents — raw body, filename in the path.
for doc in pathlib.Path("handbook").glob("*.pdf"):
api.post(f"/api/knowledge-sets/{ks_id}/knowledge-files/{doc.name}",
content=doc.read_bytes(),
headers={"Content-Type": "application/pdf"}).raise_for_status()
# 4. Attach the set to the agent.
api.post(f"/api/agents/{agent_id}/knowledge-sets/{ks_id}/attach").raise_for_status()
# 5. Use it. Ingestion is async, so allow time before expecting retrieval.
answer = api.post(f"/api/invoke/{agent_id}",
headers={"Accept": "application/json",
"Content-Type": "text/plain"},
content="What is our refund window?").raise_for_status().json()
print("".join(e.get("content", "") for e in answer["items"]))
Field names for AgentManifest, KnowledgeSetManifest and the rest come
from the spec — check /api/openapi.json for your version rather than
copying them from here.
What stays admin-only
No API key reaches the following, regardless of scopes — they need an admin
browser session. (Those that are in the spec carry x-required-scope: admin;
several are not in the spec at all.)
- Listing models and reading a single tool reference (the read-side catalogues)
- Listing, updating and deleting workflows (there is no workflow create route)
GET /api/settingsand all instance settings- User, group and auth-provider administration
- Minting API keys — a key cannot create more keys
A holder of settings:manage can write five operational tuning knobs via
PUT /api/settings/runtime (sync/ingestion timeouts, the ingestion limit and
the import max size). Seat limits (max_users) and feature gates stay
read-only and subscription-controlled: there is no route that lets an
instance raise its own limits.
Related docs
- API Keys — scope grammar and minting
- Files — knowledge uploads in detail
- Invoke API — running the agents you provision