Developers
API and MCP
RecapButler is built to be an agent-ready data layer for client meetings. AI can read everything, but writes always pass the human approval gate. Every read is org-scoped by token; every write lands in the audit trail.
Authentication
All endpoints authenticate with a Bearer token created in the app under Settings, Connect. Tokens look like rbk_<40 hex characters> and come in two scopes: read (list and inspect) and read_write (also decide cards and ingest meetings). Tokens are shown once at creation; only a hash is stored. Rate limit: 60 requests per minute per token.
curl https://recapbutler.com/api/v1/meetings \ -H "Authorization: Bearer rbk_YOUR_TOKEN"
REST endpoints
JSON in, JSON out. Errors use a single envelope: {"error": {"code", "message"}}. All responses are uncached (cache-control: no-store).
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /api/v1/meetings | read | List meetings. Query: status=pending|reviewed, limit (max 100), cursor. |
| GET | /api/v1/meetings/{id} | read | One meeting with all suggestion cards and the full audit trail. |
| GET | /api/v1/approvals | read | All cards still waiting for a human decision, across meetings. |
| POST | /api/v1/cards/{id}/decision | read_write | Decide a card: {"approval": "approved"|"edited"|"discarded", "editedText"?}. |
| GET | /api/v1/digest | read | Client digest: approved items from the last 14 days, grouped by client. |
| POST | /api/engine/ingest | read_write | Store a prepared meeting bundle. Cards land as pending suggestions. |
| POST | /api/engine/extract | read_write | Send a raw transcript; the engine extracts cards into the approval tray. |
# List pending approvals
curl https://recapbutler.com/api/v1/approvals \
-H "Authorization: Bearer rbk_YOUR_TOKEN"
# Approve a card (requires read_write scope)
curl -X POST https://recapbutler.com/api/v1/cards/CARD_ID/decision \
-H "Authorization: Bearer rbk_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"approval": "approved"}'MCP server
The MCP server lives at https://recapbutler.com/api/mcp (Streamable HTTP transport) and authenticates with the same Bearer tokens. Point Claude, or any MCP client, at it:
{
"mcpServers": {
"recapbutler": {
"type": "http",
"url": "https://recapbutler.com/api/mcp",
"headers": {
"Authorization": "Bearer rbk_YOUR_TOKEN"
}
}
}
}Available tools:
list_meetings: meetings with status and countsget_meeting: one meeting with cards and audit traillist_pending_approvals: every card behind the approval gateget_digest: the client-ready digest of approved itemsdecide_card: record a human decision (read_write scope only; audited)
Ingest and extract
Push meetings in from any source. POST a raw transcript to /api/engine/extract and the engine extracts decisions, actions and client approval states as suggestion cards, or POST a prepared bundle to /api/engine/ingest. Either way, cards land pending in the tray. Nothing is written anywhere until a human approves.
curl -X POST https://recapbutler.com/api/engine/extract \
-H "Authorization: Bearer rbk_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"transcript": "Alice: Let us move the launch to Friday...",
"title": "Acme weekly sync",
"clientName": "Acme",
"source": "upload"
}'
# -> {"meetingId": "...", "cardCount": 5}Webhooks
When approved items are written, RecapButler posts a summary to the Slack, Teams and generic webhooks configured under Settings, Connect. Slack and Teams receive a simple {"text": "..."} message; the generic webhook receives raw JSON:
{
"event": "commit",
"meetingId": "3f6c1c9a-...",
"meetingTitle": "Acme weekly sync",
"written": [
{"target": "crm", "description": "Meeting note appended to the Acme record"},
{"target": "tasks", "description": "Task created: Send revised proposal by Thursday"}
]
}The approval gate
The whole surface follows one rule: AI can read everything, but writes always pass the human approval gate. Reads are free and broad; the only write primitive is a card decision, and every decision, human or via API token, is recorded in an append-only audit trail.