Keys for your code, OAuth for assistants
An API key is for a server you run. An OAuth grant is for an app a person connects, and it can never hold more than that person may do.
Authentication
The rules, in order
01
API keys
An owner or admin creates a key in the console, after a recent sign-in. It is shown once: bmk_live_… or bmk_test_…. We store a keyed hash of it, never the key, so we cannot show it to you again. Lose it and you revoke it and make another.
A key carries its scopes, an optional address allow-list, an optional expiry and its own rate limit. A test key exists only for a sandbox workspace and a live key never for one. Every call made with it is audited with the key as the actor.
Authorization: Bearer bmk_test_…02
Scopes
A route needs the scope named on its reference entry. A few routes also need a second scope, and their summary says so. A write scope also reads what it writes. A credential that holds a scope outside its type’s ceiling is refused, whatever its document says.
| Scope | Routes |
|---|---|
actions:admin | 37 |
actions:deliver | 14 |
actions:money | 22 |
actions:propose | 3 |
actions:read | 3 |
actions:records | 31 |
activity:read | 2 |
admin:read | 12 |
bills:approve | 2 |
bills:read | 8 |
bills:write | 11 |
business:read | 19 |
clients:read | 4 |
clients:write | 6 |
estimates:read | 2 |
estimates:write | 4 |
expenses:read | 1 |
expenses:write | 3 |
invoices:read | 6 |
invoices:write | 21 |
jobs:read | 21 |
jobs:write | 19 |
messages:read | 3 |
mileage:read | 1 |
mileage:write | 2 |
organizer:read | 2 |
organizer:write | 4 |
payments:notes | 1 |
payments:read | 12 |
payments:record | 1 |
payments:refund | 1 |
recurring:read | 2 |
recurring:write | 3 |
reports:read | 17 |
sandbox:reset | 1 |
templates:read | 5 |
templates:write | 7 |
time:read | 3 |
time:write | 7 |
webhooks:manage | 7 |
workConfig:write | 3 |
03
OAuth 2.1, for apps a person connects
Assistants connect with OAuth against https://api.billingmart.com/mcp. Discovery is standard (RFC 9728 and RFC 8414), clients can register themselves (RFC 7591) or present a client metadata document, and PKCE with S256 is required.
The consent screen lists what the app asked for, grouped and in plain words, with the business picker and a choice between Ask (it may request actions) and Plan (it may only read and show what it would do). Reading contact details is off unless the person ticks it.
| Token | Lifetime | On reuse |
|---|---|---|
bmat_… | access, 1 hour | — |
bmrt_… | refresh, 30 days rolling, rotated on use | the whole grant is revoked |
04
A grant is bound to a person
Every call through a grant re-reads the person who consented. Removed from the workspace: refused. Moved to viewer: the same token now reads only. Write scopes need a recent sign-in at consent, and a second factor where the workspace requires one.
The person, or an owner or admin, can narrow a grant or revoke it from Connected apps in the console. The next call sees the change; nobody has to reconnect. No tool can change its own grant.
MCP server
Every tool is a REST v1 call under the connecting person’s grant. Anything that sends or moves money becomes a request, and the connection’s mode — Ask, Plan or Auto — decides who approves it.
Try it in your sandbox
A bmk_test_ key reaches only your sandbox workspace.