Minolith Platform API Documentation
Base URL: https://api.minolith.io
This document covers the shared foundations of every Minolith service — authentication, rate limiting, error handling, credits, and pagination. Read this first, then dive into the service-specific docs below.
Services
| Service | What it does | Cost |
|---|---|---|
| Context | Persistent knowledge base that survives between sessions | Free |
| Changelog | API-first changelog with hosted pages, widgets, and RSS feeds | 3 credits per entry |
| Feedback | Structured feedback collection via embeddable widget or API | 1 credit per item |
| Runbooks | Step-by-step procedures with progress tracking and conditional branching | 5 credits per template |
| Agents | Agent definitions, subagent management, and a community template registry | 3 credits per agent |
| Styleguide | Design tokens, components, patterns, voice rules, and managed brand assets | 2–3 credits per write |
| Documents | Foundation file uploads (PDFs, docs, spreadsheets, images) with metadata and download URLs | Free |
| Bootstrap | Load your full project state in a single call | Free |
Authentication
Every request requires an API key in the Authorization header:
Authorization: Bearer mlth_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keys are prefixed with mlth_ and scoped to a single project — you'll only ever see data belonging to that project.
Getting an API Key
- Sign up at app.minolith.io/register (14-day free trial, no card required)
- Create a project
- Go to API Keys in the project sidebar and generate a key
- Copy it immediately — it's only shown once
Agent Identity (Optional)
Set the X-Minolith-Agent header to identify which agent is making the request:
X-Minolith-Agent: riley
The system resolves the header against agent definitions in the project. If the agent exists, all operations (notes, status changes, context entries) are attributed to that agent. If the header is present but the agent name doesn't match a definition, a 422 error is returned.
This header is optional for all services except Tasks, where it's required for get_my_tasks and for proper assignment/attribution.
When configuring MCP:
claude mcp add --transport http minolith https://mcp.minolith.io \
--header "Authorization: Bearer mlth_your_api_key" \
--header "X-Minolith-Agent: riley"
Managing Keys
- Create as many keys as you need per project (e.g. production, staging, development)
- Revoke any key instantly — requests using that key will return
401immediately - The first 12 characters of each key are visible in the dashboard for identification
Authentication Errors
{
"error": {
"code": "unauthorized",
"message": "Authentication required. Provide a valid API key via the Authorization header: Bearer mlth_xxx",
"docs": "https://docs.minolith.io/api/platform#authentication"
}
}
HTTP status: 401
Rate Limiting
Every API key is limited to 100 requests per minute. Every response includes headers so you can track your usage:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1710500000
| Header | Meaning |
|---|---|
X-RateLimit-Limit |
Your per-minute request allowance |
X-RateLimit-Remaining |
How many requests you have left in this window |
X-RateLimit-Reset |
When the current window resets (Unix timestamp) |
If You Hit the Limit
You'll receive a 429 response with a Retry-After header:
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit of 100 requests per minute exceeded. Retry after 12 seconds.",
"retry_after": 12,
"docs": "https://docs.minolith.io/api/platform#rate-limiting"
}
}
Wait for the number of seconds in retry_after, then try again.
Error Responses
Every error across every service uses the same structure:
{
"error": {
"code": "invalid_type",
"message": "The type 'note' is not valid. Accepted values are: rule, pattern, snippet, decision, fact, warning, event.",
"field": "type",
"docs": "https://docs.minolith.io/api/context#entry-types",
"suggestion": "Did you mean 'fact'?"
}
}
Fields
| Field | Always present? | What it tells you |
|---|---|---|
code |
Yes | A machine-readable error type (snake_case) |
message |
Yes | A plain-language explanation of what went wrong |
field |
No | Which input field caused the error |
docs |
Yes | Link to the relevant documentation |
suggestion |
No | A recommended fix (e.g. fuzzy-matched enum value) |
HTTP Status Codes
| Status | Meaning | Example |
|---|---|---|
400 |
Bad Request | Malformed JSON body |
401 |
Unauthorized | Missing or invalid API key |
402 |
Payment Required | Spending cap exceeded |
403 |
Forbidden | Action not allowed (e.g. editing an immutable entry) |
404 |
Not Found | Resource doesn't exist in your project |
409 |
Conflict | Duplicate resource |
422 |
Validation Error | Well-formed request but invalid data |
429 |
Too Many Requests | Rate limit exceeded |
500 |
Server Error | Something unexpected broke |
Handling Errors
- Check the HTTP status code for the category
- Read
error.codeto identify the specific problem - Check
error.fieldto see which input to fix (if present) - Check
error.suggestionfor a recommended correction (if present) - Follow
error.docsfor full details on the relevant feature
Credits and Pricing
Minolith uses a simple pay-as-you-go credit system. 1 credit = $0.01 USD.
What's free
- All reads — GET requests never cost anything
- Context — the entire Context service is free, no limits for subscribers
- Projects — create as many as you need at no extra cost
- Updates and deletes — modifying or removing data is always free
What costs credits
| Action | Cost |
|---|---|
| Create a changelog entry | 3 credits ($0.03) |
| Submit feedback | 1 credit ($0.01) |
| Create a runbook template | 5 credits ($0.05) |
| Create an agent definition | 3 credits ($0.03) |
| Define styleguide tokens/patterns/voice | 2 credits ($0.02) |
| Define a styleguide component | 3 credits ($0.03) |
| Upload a styleguide asset | 3 credits ($0.03) |
| Storage | 5 credits ($0.05) per MB/month |
Base subscription
$5/month includes 500 credits. Any usage beyond that is billed as overage at $0.01/credit. Team plans are available at $15/month (1,500 credits) and $25/month (2,500 credits).
Spending Caps
Set a monthly cap in the dashboard (Usage page) to prevent unexpected charges. If a write would exceed your cap, you'll get a 402 response:
{
"error": {
"code": "spending_cap_exceeded",
"message": "This action would exceed your monthly spending cap of 500 credits. Current usage: 498 credits. This action costs 1 credit. Increase your cap in the dashboard or wait for the next billing period.",
"docs": "https://docs.minolith.io/api/platform#spending-caps",
"current_usage": 498,
"cap": 500,
"action_cost": 1
}
}
Pagination
All list endpoints use cursor-based pagination. Pass limit to control page size (default 20, max 100) and cursor to fetch the next page.
Response Format
{
"data": [
{ "id": "ctx_abc123", "..." : "..." },
{ "id": "ctx_def456", "..." : "..." }
],
"pagination": {
"has_more": true,
"next_cursor": "ctx_def456",
"limit": 20
}
}
Paging Through Results
- Make your first request:
GET /v1/context/entries?limit=50 - If
has_moreistrue, passnext_cursoras thecursorparameter:GET /v1/context/entries?limit=50&cursor=ctx_def456 - Repeat until
has_moreisfalse
Health Check
GET /v1/health
Returns {"status": "ok"} if the platform is running. No authentication required.
MCP Server
Minolith provides an MCP (Model Context Protocol) server so AI coding tools can access all Minolith services as native tools. It works with Claude Code, Claude Desktop, Cursor, Windsurf, GitHub Copilot, and any other MCP-compatible client.
The MCP server uses the same API key as the REST API. All data is scoped to the key's project.
Setup
Claude Code
claude mcp add --transport http minolith https://mcp.minolith.io \
--header "Authorization: Bearer mlth_yourkey" \
--header "X-Minolith-Agent: your-agent-name"
Cursor
Add to .cursor/mcp.json (project) or ~/.cursor/mcp.json (global):
{
"mcpServers": {
"minolith": {
"url": "https://mcp.minolith.io",
"headers": {
"Authorization": "Bearer mlth_yourkey",
"X-Minolith-Agent": "your-agent-name"
}
}
}
}
Restart Cursor after saving — MCP servers only load at startup.
Windsurf
Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"minolith": {
"serverUrl": "https://mcp.minolith.io",
"headers": {
"Authorization": "Bearer mlth_yourkey",
"X-Minolith-Agent": "your-agent-name"
}
}
}
}
GitHub Copilot (VS Code)
Add to .vscode/mcp.json (workspace) or use the command palette → MCP: Open User Configuration (global):
{
"servers": {
"minolith": {
"type": "http",
"url": "https://mcp.minolith.io",
"headers": {
"Authorization": "Bearer mlth_yourkey",
"X-Minolith-Agent": "your-agent-name"
}
}
}
}
Other Clients
Point any MCP client's HTTP transport at https://mcp.minolith.io with the Authorization: Bearer mlth_yourkey and X-Minolith-Agent: your-agent-name headers.
Protocol Details
The server implements JSON-RPC 2.0 over Streamable HTTP:
- Endpoint:
POST https://mcp.minolith.io/ - Content-Type:
application/json - Auth:
Authorization: Bearer mlth_yourkey
Supported methods:
| Method | What it does |
|---|---|
initialize |
Handshake — negotiates capabilities |
tools/list |
Returns all available tools and their schemas |
tools/call |
Runs a tool with the given arguments |
ping |
Health check |
Server Capabilities
The server returns these capabilities during initialize:
{
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": { "listChanged": false }
},
"serverInfo": {
"name": "minolith",
"version": "1.4.0"
}
}
Calling a Tool
{
"jsonrpc": "2.0",
"id": "1",
"method": "tools/call",
"params": {
"name": "store_context",
"arguments": {
"type": "rule",
"title": "Example rule",
"body": "Rule details..."
}
}
}
Error Handling
Tool errors come back as normal tool results with isError: true — the agent sees the error message and can react to it.
Protocol errors (bad JSON, unknown method) use standard JSON-RPC error codes:
| Code | Meaning |
|---|---|
-32700 |
Parse error (invalid JSON) |
-32600 |
Invalid request |
-32601 |
Method not found |
-32602 |
Invalid params |
Available Tools
Each service exposes its own set of tools. See the individual service docs for full schemas and examples.
| Service | Count | Tools |
|---|---|---|
| Context | 11 | store_context, get_context, update_context, delete_context, bulk_store_context, bulk_update_context, bulk_delete_context, log_event, get_recent_events, list_tags, list_scopes |
| Changelog | 6 | create_changelog_entry, update_changelog_entry, list_changelog_entries, create_changelog_version, publish_changelog_entry, publish_changelog_version |
| Feedback | 5 | submit_feedback, list_feedback, get_feedback_item, update_feedback_status, add_feedback_note |
| Runbooks | 9 | create_runbook, list_runbooks, start_run, get_current_step, advance_step, skip_step, fail_step, pause_run, list_runs |
| Agents | 8 | bootstrap, get_agent, list_agents, create_agent, update_agent, sync_agents, browse_registry, install_registry_agent |
| Styleguide | 11 | get_styleguide, get_tokens, get_component, define_tokens, define_component, define_pattern, define_voice, search_styleguide, upload_asset, get_asset, list_assets |
| Tasks | 8 | get_my_tasks, get_task, create_task, update_task_status, add_task_note, assign_task, get_team_feed, get_workflow |
| Documents | 5 | upload_document, list_documents, get_document, update_document, delete_document |
ID Format
Every resource ID is a prefixed UUID — the prefix tells you what kind of resource it is at a glance. IDs are case-sensitive and globally unique.
| Resource | Prefix | Example |
|---|---|---|
| Account | acc_ |
acc_a1b2c3d4e5f6 |
| Project | prj_ |
prj_x9y8z7w6v5u4 |
| API Key | key_ |
key_m3n4o5p6q7r8 |
| Context Entry | ctx_ |
ctx_j1k2l3m4n5o6 |
| Changelog Entry | ent_ |
ent_a1b2c3d4e5f6 |
| Changelog Version | ver_ |
ver_x9y8z7w6v5u4 |
| Feedback Item | fbk_ |
fbk_a1b2c3d4e5f6 |
| Feedback Note | fbn_ |
fbn_x9y8z7w6v5u4 |
| Runbook | rnb_ |
rnb_a1b2c3d4e5f6 |
| Runbook Step | rbs_ |
rbs_x9y8z7w6v5u4 |
| Runbook Run | run_ |
run_a1b2c3d4e5f6 |
| Runbook Run Step | rrs_ |
rrs_x9y8z7w6v5u4 |
| Agent Definition | agt_ |
agt_a1b2c3d4e5f6 |
| Agent Registry | agr_ |
agr_x9y8z7w6v5u4 |
| Styleguide Token | sgt_ |
sgt_a1b2c3d4e5f6 |
| Styleguide Component | sgc_ |
sgc_x9y8z7w6v5u4 |
| Styleguide Pattern | sgp_ |
sgp_a1b2c3d4e5f6 |
| Styleguide Voice | sgv_ |
sgv_x9y8z7w6v5u4 |
| Styleguide Asset | sga_ |
sga_a1b2c3d4e5f6 |
| Team | tem_ |
tem_a1b2c3d4e5f6 |
| Team Member | tmm_ |
tmm_x9y8z7w6v5u4 |
| Team Invite | tmi_ |
tmi_a1b2c3d4e5f6 |
| Project Member | pmm_ |
pmm_x9y8z7w6v5u4 |
| Task | tsk_ |
tsk_a1b2c3d4e5f6 |
| Task Note | tsn_ |
tsn_x9y8z7w6v5u4 |
| Project Workflow | wfl_ |
wfl_a1b2c3d4e5f6 |
| Document | doc_ |
doc_a1b2c3d4e5f6 |
MCP Token Footprint
The full Minolith MCP tool set loads at 12,307 tokens. This is the cost of registering all 61 tools in your agent's context window before any calls are made.
For context-constrained agents, this is roughly 1.2% of a 1M-token window or 6.2% of a 200K-token window. The token cost is fixed regardless of how many tools are actually used during a session — tools are registered once at connection time.
MCP Tool Selection
By default, all 61 tools are returned in tools/list when your agent connects. You can reduce the token footprint by configuring which tools load.
How it works
Tool selection is configured at two levels with the following priority:
- Agent
tools_allowed— if the agent definition has a non-emptytools_allowedarray, only those tools (plus protected tools) are returned - API key
mcp_tools— if the API key has a non-emptymcp_toolsconfiguration, those tools (plus protected tools) are returned - Default — if neither is set, all 61 tools are returned
Agent-level configuration always overrides key-level configuration when both are set.
Protected tools
The following 12 tools are always included regardless of your selection. They cannot be deselected:
bootstrap- All Context service tools:
store_context,get_context,update_context,delete_context,bulk_store_context,bulk_update_context,bulk_delete_context,log_event,get_recent_events,list_tags,list_scopes
tools/call is unaffected
Tool selection only controls what appears in tools/list. Any tool can still be called via tools/call regardless of the selection — this is purely a token optimisation, not a security boundary.
Configuration
Configure via the dashboard:
- API keys: Edit an API key from your project's API Keys page and use the tool picker
- Agents: Edit an agent definition and use the MCP Tools Allowed picker
Or via the API/MCP:
- Agent definitions: Set the
tools_allowedfield to a JSON array of tool names - API keys: Set the
mcp_toolsfield (database column, no REST endpoint yet)