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>; create POST; update PUT /<id>; delete DELETE /<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.

WhatURL
MCP endpoint (JSON-RPC over HTTP)https://YOUR-HOST/api/v1/mcp
OAuth authorization-server metadatahttps://YOUR-HOST/.well-known/oauth-authorization-server
OAuth protected-resource metadatahttps://YOUR-HOST/.well-known/oauth-protected-resource

Connect from Claude (web or desktop)

  1. Claude → Settings → Connectors → Add custom connector.
  2. Paste the MCP endpoint URL and click Connect. Claude discovers the OAuth server and registers itself — no client id to copy.
  3. 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

ToolScopePurpose
crm_describereadEntities and fields (type, required, writable, enum, relations)
crm_list / crm_getreadSearch with filter/order/pagination; fetch one row
crm_create / crm_update / crm_deletewriteWrite rows; create and delete require confirm: true
crmx_findreadFuzzy search across contacts, companies, quotes, invoices, products, activities
crmx_create_quote, crmx_create_invoice, crmx_convert_quote_to_invoicewriteSales flow with detail questions
crmx_record_payment, crmx_scan_receiptwritePayments and AI receipt scanning
crmx_my_day, crmx_pipeline_summary, crmx_distance, crmx_log_activity, crmx_email_document, crmx_drive_listmixedBriefings, reporting, travel distance, activity logging, sending documents, Drive
gc_pdf_preview, gc_regenerate_pdfread / writePreview 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).