Documentation
REST API & MCP (Claude)
JWT authentication, routes, RBAC, realtime, and connecting Claude through MCP.
REST API
Every table in the schema is exposed under /api/v1/<Table> with JWT bearer authentication. The same routes without the /api/v1/ prefix serve the browser UI with a cookie session.
POST /api/v1/Authy/auth
Content-Type: application/json
{ "u": "you", "p": "secret" }
→ { "status": "success", "token": "eyJhbGciOi…", "expires": 1735776000 }
GET /api/v1/Contact?filter[type]=Client&order[name]=asc&limit=50
Authorization: Bearer eyJhbGciOi…
- List
GET /api/v1/<Table>— filter, order, select and pagination in the query string. - Read
GET /api/v1/<Table>/<id>; createPOST; updatePUT /<id>; deleteDELETE /<id>. - Responses use one envelope:
{ status, data, error, meta }. Validation errors list the offending fields. - Record rights and route RBAC apply exactly as in the UI (see Users, groups & security). Every call is written to the API log.
- Custom actions (send quote, convert to invoice, scan receipt…) are regular routes under the table, e.g.
POST /api/v1/Quote/<id>/convert.
The full generated reference — request headers, envelope, constants, every resource — is in .admin/docs/API.md of your installation.
MCP server for Claude
BillBoy exposes a Model Context Protocol endpoint with OAuth 2.1 (dynamic client registration, PKCE, refresh tokens), so Claude can use your CRM as a set of typed tools within your own rights.
| What | URL |
|---|---|
| MCP endpoint (JSON-RPC over HTTP) | https://YOUR-HOST/api/v1/mcp |
| OAuth authorization-server metadata | https://YOUR-HOST/.well-known/oauth-authorization-server |
| OAuth protected-resource metadata | https://YOUR-HOST/.well-known/oauth-protected-resource |
Connect from Claude (web or desktop)
- Claude → Settings → Connectors → Add custom connector.
- Paste the MCP endpoint URL and click Connect. Claude discovers the OAuth server and registers itself — no client id to copy.
- Sign in with your BillBoy credentials and approve the scopes (
crm:read,crm:write,offline_access).
Connect from Claude Code
claude mcp add --transport http billboy https://YOUR-HOST/api/v1/mcp
# then in Claude Code: /mcp → Authenticate
Tools
| Tool | Scope | Purpose |
|---|---|---|
crm_describe | read | Entities and fields (type, required, writable, enum, relations) |
crm_list / crm_get | read | Search with filter/order/pagination; fetch one row |
crm_create / crm_update / crm_delete | write | Write rows; create and delete require confirm: true |
crmx_find | read | Fuzzy search across contacts, companies, quotes, invoices, products, activities |
crmx_create_quote, crmx_create_invoice, crmx_convert_quote_to_invoice | write | Sales flow with detail questions |
crmx_record_payment, crmx_scan_receipt | write | Payments and AI receipt scanning |
crmx_my_day, crmx_pipeline_summary, crmx_distance, crmx_log_activity, crmx_email_document, crmx_drive_list | mixed | Briefings, reporting, travel distance, activity logging, sending documents, Drive |
gc_pdf_preview, gc_regenerate_pdf | read / write | Preview a document as HTML; regenerate its PDF |
Tools never invent values: a create with missing required fields returns the list of what is needed. Writes are executed only with an explicit confirmation, and the user’s record rights still apply.
Realtime
An optional OpenSwoole sidecar pushes {op:"change", t:"<table>"} frames over WebSocket whenever a table changes; open lists re-fetch themselves. Enable with GC_RT_ENABLED="1" and a WebSocket proxy rule in your vhost; the app works unchanged when the sidecar is down.
Mobile app
The mobile/ directory contains an Expo (React Native) app that talks to the same API with a JWT and registers the device for push notifications (Settings → Push devices).