Skip to content

Workspace and access

Explore here

Workspace and access

The workspace a credential acts in, its plan, how it pays for it, usage and AI credits, the connection an assistant holds, the people, keys and apps with access, and resetting a sandbox to its demo data.

business

Get

GET/v1/business

The tenant and its businesses: terminology, presets, fee types, invoice fields, currencies, plan and cap status.

Scope
business:read
Effect
Read only
MCP tool
get_business_context
Retries
Safe to repeat

Returns

data: BusinessContext

Example requestSample
curl -X GET "https://api.billingmart.com/v1/business" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

business

Upsert item preset

POST/v1/business/item-presets

Add a product or service to a business, or change one by its key; the rest of the business model is never written. Adding refuses a key or a name another item already has; changing replaces that one item whole. A price is integer minor units in the business currency. Changing a saved item’s price (its basis, unit price or rate) is refused for a connected app or an API key (ITEM_PRICE_CONSOLE_ONLY): a person changes prices in BillingMart.

Scope
invoices:write
Effect
Writes a draft or record
MCP tool
upsert_item_preset
Retries
Send an Idempotency-Key; a repeat replays the stored answer for 24 hours

Request body

JSON. Money is an integer count of minor units beside its currency; quantities are thousandths.

Upsert item preset request body
FieldTypeNotes
businessIdrequiredid—
intentrequiredenumOne of add, change
keyoptionalstringup to 64 chars
labelrequiredstringup to 120 chars
rateBasisrequiredenumOne of fixed, hourly, daily, weekly, monthly, perUnit, perMile, perKilometre, percentage
defaultUnitPriceoptionalobject—
defaultUnitPrice.minorUnitsrequiredinteger—
defaultUnitPrice.currencyrequiredCurrency—
defaultRateBasisPointsoptionalintegermin -10000000 · max 10000000
taxTreatmentoptionalenumOne of taxable, exempt, zeroRated, reverseCharge

Returns

data: object

Errors this route can answer besides the shared ones: ALREADY_EXISTS, BUSINESS_NOT_FOUND, ITEM_PRICE_CONSOLE_ONLY.

Example requestSample
curl -X POST "https://api.billingmart.com/v1/business/item-presets" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"businessId":"<businessId>","intent":"add","label":"<label>","rateBasis":"fixed","defaultUnitPrice":{"minorUnits":0,"currency":"USD"}}'

business

List item presets

GET/v1/business/item-presets

List a business’s products and services by name, or with archived=true the ones archived.

Scope
business:read
Effect
Read only
MCP tool
list_item_presets
Retries
Safe to repeat

Parameters

List item presets parameters
NameInTypeNotes
businessIdrequiredqueryid—
archivedoptionalqueryboolean—

Returns

data: ItemPreset[]. Pass meta.cursor back as cursor for the next page.

Errors this route can answer besides the shared ones: BUSINESS_NOT_FOUND.

Example requestSample
curl -X GET "https://api.billingmart.com/v1/business/item-presets" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

business

Archive item preset

POST/v1/business/item-presets/{key}/archive

Take a product or service out of the pickers; it is kept and can be restored. Documents already holding its lines keep them.

Scope
invoices:write
Effect
Writes a draft or record
MCP tool
archive_item_preset
Retries
Send an Idempotency-Key; a repeat replays the stored answer for 24 hours

Parameters

Archive item preset parameters
NameInTypeNotes
keyrequiredpathstringup to 64 chars

Request body

JSON. Money is an integer count of minor units beside its currency; quantities are thousandths.

Archive item preset request body
FieldTypeNotes
businessIdrequiredid—

Returns

data: object

Errors this route can answer besides the shared ones: NOT_FOUND, BUSINESS_NOT_FOUND.

Example requestSample
curl -X POST "https://api.billingmart.com/v1/business/item-presets/{key}/archive" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"businessId":"<businessId>"}'

business

Restore item preset

POST/v1/business/item-presets/{key}/restore

Put an archived product or service back, exactly as it was; refused if its key or name has been taken since.

Scope
invoices:write
Effect
Writes a draft or record
MCP tool
restore_item_preset
Retries
Send an Idempotency-Key; a repeat replays the stored answer for 24 hours

Parameters

Restore item preset parameters
NameInTypeNotes
keyrequiredpathstringup to 64 chars

Request body

JSON. Money is an integer count of minor units beside its currency; quantities are thousandths.

Restore item preset request body
FieldTypeNotes
businessIdrequiredid—

Returns

data: object

Errors this route can answer besides the shared ones: NOT_FOUND, ALREADY_EXISTS, BUSINESS_NOT_FOUND.

Example requestSample
curl -X POST "https://api.billingmart.com/v1/business/item-presets/{key}/restore" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"businessId":"<businessId>"}'

usage

Get

GET/v1/usage

This month’s sends (invoices, estimates and payment-link payments, in total and by kind) against the plan cap, this month’s executed assistant actions against the plan’s allowance, and this month’s AI calls and tokens against the AI guard: a safety ceiling that stops a runaway, separate from AI credits; for a new workspace, its plan trial and when it ends.

Scope
business:read
Effect
Read only
MCP tool
usage_status
Retries
Safe to repeat

Returns

data: object

Example requestSample
curl -X GET "https://api.billingmart.com/v1/usage" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

plan

Upgrade options

GET/v1/plan/upgrade-options

The plans this workspace may upgrade to, with their prices, and the link the workspace owner opens to accept one.

Scope
business:read
Effect
Read only
MCP tool
get_upgrade_options
Retries
Safe to repeat

Returns

data: PlanUpgradeOptions

Example requestSample
curl -X GET "https://api.billingmart.com/v1/plan/upgrade-options" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

ai

Credits

GET/v1/ai/credits

The workspace’s AI balance (expired credit set aside) and what it is made of — the plan’s monthly allowance, granted and bought credit with when each expires, any debt — its price per million tokens, the model its AI runs on, what each AI task typically costs, the credit packs on offer with their prices, whether the Agent is open (by plan or by trial), and the capability-free link where the owner buys more.

Scope
business:read
Effect
Read only
MCP tool
ai_credits_status
Retries
Safe to repeat

Returns

data: AiCreditsStatus

Example requestSample
curl -X GET "https://api.billingmart.com/v1/ai/credits" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

ai

Credit history

GET/v1/ai/credits/history

The workspace’s AI credits history, newest first: each grant, purchase, AI use (with its feature), adjustment, reversal, expiry and monthly allowance, in credits (10 tokens each) and the balance it left. Filter by kind; page with before.

Scope
business:read
Effect
Read only
MCP tool
list_ai_credit_history
Retries
Safe to repeat

Parameters

Credit history parameters
NameInTypeNotes
kindoptionalqueryenumOne of grant, purchase, usage, adjustment, reversal, expiry, allowance
beforeoptionalquerystring (date-time)—
limitoptionalqueryintegermin 1 · max 100

Returns

data: AiCreditHistory

Example requestSample
curl -X GET "https://api.billingmart.com/v1/ai/credits/history" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

plan

Preview change

GET/v1/plan/preview-change

What moving this workspace to a plan and billing interval would charge now (with proration for an upgrade), whether it is an upgrade (charged now), a downgrade or a cancellation (at the period end), and when it takes effect.

Scope
business:read
Effect
Read only
MCP tool
preview_plan_change
Retries
Safe to repeat

Parameters

Preview change parameters
NameInTypeNotes
planIdrequiredqueryid—
intervalrequiredqueryenumOne of monthly, annual · default "monthly"

Returns

data: PlanChangePreview

Example requestSample
curl -X GET "https://api.billingmart.com/v1/plan/preview-change" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

billing

Get

GET/v1/billing

How this workspace pays for its plan: the provider (Stripe, an app store, or BillingMart invoice), the status, the plan and interval, the renewal date, any scheduled change, whether a payment is past due, whether a card is saved, and, for a new workspace, its plan trial.

Scope
business:read
Effect
Read only
MCP tool
billing_status
Retries
Safe to repeat

Returns

data: object

Example requestSample
curl -X GET "https://api.billingmart.com/v1/billing" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

billing

Receipt

GET/v1/billing/receipts/{invoiceId}

The receipt for one paid BillingMart invoice of this workspace: its number, when it was paid, the plan and interval, each line (an upgrade shows its proration credit and charge), the total, the card’s brand and last four, and the next renewal.

Scope
business:read
Effect
Read only
MCP tool
get_billing_receipt
Retries
Safe to repeat

Parameters

Receipt parameters
NameInTypeNotes
invoiceIdrequiredpathstringmatches ^in_[A-Za-z0-9_]{1,200}$

Returns

data: BillingReceipt

Example requestSample
curl -X GET "https://api.billingmart.com/v1/billing/receipts/{invoiceId}" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

connection

Get

GET/v1/connection

This connection: its mode (plan, ask or auto), its effective scopes, per action kind the remaining auto-approve allowance for today, and the workspace’s executed assistant actions this month against the plan’s allowance.

Scope
business:read
Effect
Read only
MCP tool
get_connection_status
Retries
Safe to repeat

Returns

data: ConnectionStatus

Example requestSample
curl -X GET "https://api.billingmart.com/v1/connection" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

search

Records

GET/v1/search

Search invoices, estimates, clients, jobs and vendors by number or name. Every word must appear (case and accents ignored). A type is searched only when the credential holds its read scope. At most 25 results a page, and at most 400 records read per request: a page can be short and still carry a cursor, so follow `cursor` until it is absent.

Scope
business:read
Effect
Read only
MCP tool
search_records
Retries
Safe to repeat

Parameters

Records parameters
NameInTypeNotes
qrequiredquerystringup to 100 chars
typeoptionalqueryenumOne of invoice, estimate, client, job, vendor
limitoptionalqueryintegermin 1 · max 25
cursoroptionalquerystringup to 256 chars

Returns

data: SearchResult[]. Pass meta.cursor back as cursor for the next page.

Example requestSample
curl -X GET "https://api.billingmart.com/v1/search" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

ai

Proposals

GET/v1/ai/proposals

What the AI proposed, newest first: the task, the validated output and the verdict a person gave it. The output is model text about real records and comes back inside the data envelope.

Scope
invoices:read
Effect
Read only
MCP tool
list_ai_proposals
Retries
Safe to repeat

Parameters

Proposals parameters
NameInTypeNotes
limitoptionalqueryintegermin 1 · max 50
cursoroptionalquerystringup to 256 chars
taskoptionalquerystringup to 64 chars

Returns

data: AiProposal[]. Pass meta.cursor back as cursor for the next page.

Example requestSample
curl -X GET "https://api.billingmart.com/v1/ai/proposals" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

ai

Suggest line descriptions

POST/v1/ai/line-descriptions

Suggest up to three line-item descriptions for a short hint, in the business’s own terms. Text only — nothing is added to any invoice.

Scope
invoices:write
Effect
Read only
MCP tool
suggest_line_descriptions
Retries
Send an Idempotency-Key; a repeat replays the stored answer for 24 hours

Request body

JSON. Money is an integer count of minor units beside its currency; quantities are thousandths.

Suggest line descriptions request body
FieldTypeNotes
businessIdrequiredid—
hintrequiredstringat least 3 chars · up to 300 chars

Returns

data: object

Errors this route can answer besides the shared ones: AI_DISABLED, AI_CAP_REACHED, AI_CREDITS_EXHAUSTED.

Example requestSample
curl -X POST "https://api.billingmart.com/v1/ai/line-descriptions" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"businessId":"<businessId>","hint":"<hint>"}'

ai

Explain payment plan

POST/v1/recurring/{recurringId}/explanation

Draft a plain-language explanation of an installment plan and save it as a DRAFT beside the schedule. An explanation a customer already saw is untouched; a person publishes a new one.

Scope
recurring:write
Effect
Writes a draft or record
MCP tool
explain_payment_plan
Retries
Send an Idempotency-Key; a repeat replays the stored answer for 24 hours

Parameters

Explain payment plan parameters
NameInTypeNotes
recurringIdrequiredpathid—

Returns

data: object

Errors this route can answer besides the shared ones: AI_DISABLED, AI_CAP_REACHED, AI_CREDITS_EXHAUSTED.

Example requestSample
curl -X POST "https://api.billingmart.com/v1/recurring/{recurringId}/explanation" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

ai

Draft dunning ladder

POST/v1/businesses/{businessId}/dunning-ladder-draft

Draft a reminder subject and body for each step of a business’s dunning cadence, escalating in tone. Text only — the cadence itself is not changed and nothing is sent.

Scope
invoices:write
Effect
Read only
MCP tool
draft_dunning_ladder
Retries
Send an Idempotency-Key; a repeat replays the stored answer for 24 hours

Parameters

Draft dunning ladder parameters
NameInTypeNotes
businessIdrequiredpathid—

Request body

JSON. Money is an integer count of minor units beside its currency; quantities are thousandths.

Draft dunning ladder request body
FieldTypeNotes
toneoptionalenumOne of friendly, neutral, firm

Returns

data: object

Errors this route can answer besides the shared ones: AI_DISABLED, AI_CAP_REACHED, AI_CREDITS_EXHAUSTED.

Example requestSample
curl -X POST "https://api.billingmart.com/v1/businesses/{businessId}/dunning-ladder-draft" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

ai

Job summary

POST/v1/jobs/{jobId}/ai-summary

A short summary of one work record: a headline, its status, next steps and what needs attention. Returns the stored summary and whether the record has changed since; with `refresh`, makes a new one when it has (this uses AI credits). Every figure in it is filled in by the server from the record’s own computed figures, never written by the model.

Scope
jobs:read
Effect
Read only
MCP tool
summarize_job
Retries
Send an Idempotency-Key; a repeat replays the stored answer for 24 hours

Parameters

Job summary parameters
NameInTypeNotes
jobIdrequiredpathid—

Request body

JSON. Money is an integer count of minor units beside its currency; quantities are thousandths.

Job summary request body
FieldTypeNotes
refreshoptionalboolean—

Returns

data: object

Errors this route can answer besides the shared ones: NOT_FOUND, AI_DISABLED, AI_CAP_REACHED, AI_CREDITS_EXHAUSTED.

Example requestSample
curl -X POST "https://api.billingmart.com/v1/jobs/{jobId}/ai-summary" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

ai

Job draft note

POST/v1/jobs/{jobId}/ai-draft-note

Draft an internal note for one work record from a short instruction and the record’s recent activity. Returns the draft only; save it with jobs.notes.add. This uses AI credits.

Scope
jobs:read
Effect
Read only
MCP tool
draft_job_note
Retries
Send an Idempotency-Key; a repeat replays the stored answer for 24 hours

Parameters

Job draft note parameters
NameInTypeNotes
jobIdrequiredpathid—

Request body

JSON. Money is an integer count of minor units beside its currency; quantities are thousandths.

Job draft note request body
FieldTypeNotes
instructionoptionalstringup to 200 chars

Returns

data: object

Errors this route can answer besides the shared ones: NOT_FOUND, PERMISSION_DENIED, AI_DISABLED, AI_CAP_REACHED, AI_CREDITS_EXHAUSTED.

Example requestSample
curl -X POST "https://api.billingmart.com/v1/jobs/{jobId}/ai-draft-note" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

ai

Job draft message

POST/v1/jobs/{jobId}/ai-draft-message

Draft an email or a text from the business to one work record’s client, from an optional short instruction and the record’s recent activity. Returns the draft only and sends nothing; send it with jobs.messages.send. A text draft fits one text message; neither draft carries a link (the send adds the record’s own). This uses AI credits.

Scope
jobs:read
Effect
Read only
MCP tool
draft_job_message
Retries
Send an Idempotency-Key; a repeat replays the stored answer for 24 hours

Parameters

Job draft message parameters
NameInTypeNotes
jobIdrequiredpathid—

Request body

JSON. Money is an integer count of minor units beside its currency; quantities are thousandths.

Job draft message request body
FieldTypeNotes
channelrequiredenumOne of email, sms
instructionoptionalstringup to 200 chars

Returns

data: object

Errors this route can answer besides the shared ones: NOT_FOUND, PERMISSION_DENIED, AI_DISABLED, AI_CAP_REACHED, AI_CREDITS_EXHAUSTED.

Example requestSample
curl -X POST "https://api.billingmart.com/v1/jobs/{jobId}/ai-draft-message" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"channel":"email"}'

ai

Job suggest updates

POST/v1/jobs/{jobId}/ai-suggest-updates

Suggest a few updates for one work record from its recent activity: a next action, a move to another of its type’s stages, or an answer to one of its type’s fields. Each is checked against the record’s type and is never a money field. Returns suggestions only and applies nothing; apply one with the record’s own operations. This uses AI credits.

Scope
jobs:read
Effect
Read only
MCP tool
suggest_job_updates
Retries
Send an Idempotency-Key; a repeat replays the stored answer for 24 hours

Parameters

Job suggest updates parameters
NameInTypeNotes
jobIdrequiredpathid—

Returns

data: object

Errors this route can answer besides the shared ones: NOT_FOUND, PERMISSION_DENIED, AI_DISABLED, AI_CAP_REACHED, AI_CREDITS_EXHAUSTED.

Example requestSample
curl -X POST "https://api.billingmart.com/v1/jobs/{jobId}/ai-suggest-updates" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

ai

Generate business model

POST/v1/business/type-proposal

Propose a business type model (terminology, item presets, fee types, tax and terms) from a description. It returns a proposal and applies nothing; an owner or admin applies a model in the console. An owner’s or admin’s connection only.

Scope
templates:write
Effect
Read only
MCP tool
generate_business_model
Retries
Send an Idempotency-Key; a repeat replays the stored answer for 24 hours

Request body

JSON. Money is an integer count of minor units beside its currency; quantities are thousandths.

Generate business model request body
FieldTypeNotes
descriptionrequiredstringat least 10 chars · up to 2000 chars

Returns

data: object

Errors this route can answer besides the shared ones: AI_DISABLED, AI_CAP_REACHED, AI_CREDITS_EXHAUSTED.

Example requestSample
curl -X POST "https://api.billingmart.com/v1/business/type-proposal" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"description":"<description>"}'

ai

Record feedback

POST/v1/ai/proposals/{proposalId}/feedback

Record whether a proposal was accepted, edited or rejected. The latest verdict wins and each change is its own audit entry.

Scope
invoices:write
Effect
Writes a draft or record
MCP tool
record_ai_feedback
Retries
Send an Idempotency-Key; a repeat replays the stored answer for 24 hours

Parameters

Record feedback parameters
NameInTypeNotes
proposalIdrequiredpathid—

Request body

JSON. Money is an integer count of minor units beside its currency; quantities are thousandths.

Record feedback request body
FieldTypeNotes
verdictrequiredenumOne of accepted, edited, rejected

Returns

data: object

Example requestSample
curl -X POST "https://api.billingmart.com/v1/ai/proposals/{proposalId}/feedback" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"verdict":"accepted"}'

sandbox

Reset

POST/v1/admin/sandbox/reset

Reset this SANDBOX workspace to its demo data: the clients, invoices, estimates, bills, time, expenses and mileage are replaced, and numbering and the send count start again. Members, keys, settings and the audit log are kept. Refused on a live workspace. Answers the workspace as business.get shows it.

Scope
sandbox:reset
Effect
Writes a draft or record
MCP tool
reset_sandbox
Retries
Send an Idempotency-Key; a repeat replays the stored answer for 24 hours

Returns

data: object

Errors this route can answer besides the shared ones: NOT_AVAILABLE.

Example requestSample
curl -X POST "https://api.billingmart.com/v1/admin/sandbox/reset" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

members

List

GET/v1/admin/members

List the people in this workspace: role, business confinement, active state.

Scope
admin:read
Effect
Read only
MCP tool
list_members
Retries
Safe to repeat

Parameters

List parameters
NameInTypeNotes
limitoptionalqueryintegermin 1 · max 50
cursoroptionalquerystringup to 256 chars

Returns

data: TenantMember[]. Pass meta.cursor back as cursor for the next page.

Example requestSample
curl -X GET "https://api.billingmart.com/v1/admin/members" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

invitations

List

GET/v1/admin/invitations

List invitations. The token hash is never returned and the address is masked.

Scope
admin:read
Effect
Read only
MCP tool
list_invitations
Retries
Safe to repeat

Parameters

List parameters
NameInTypeNotes
limitoptionalqueryintegermin 1 · max 50
cursoroptionalquerystringup to 256 chars

Returns

data: Invitation[]. Pass meta.cursor back as cursor for the next page.

Example requestSample
curl -X GET "https://api.billingmart.com/v1/admin/invitations" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

api keys

List

GET/v1/admin/api-keys

List API keys: name, display prefix, scopes, environment, state. Never the hash.

Scope
admin:read
Effect
Read only
MCP tool
list_api_keys
Retries
Safe to repeat

Parameters

List parameters
NameInTypeNotes
limitoptionalqueryintegermin 1 · max 50
cursoroptionalquerystringup to 256 chars

Returns

data: ApiKey[]. Pass meta.cursor back as cursor for the next page.

Example requestSample
curl -X GET "https://api.billingmart.com/v1/admin/api-keys" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

connections

List

GET/v1/admin/connected-apps

List connected apps (OAuth grants): client, scopes, mode, person, revocation.

Scope
admin:read
Effect
Read only
MCP tool
list_connected_apps
Retries
Safe to repeat

Parameters

List parameters
NameInTypeNotes
limitoptionalqueryintegermin 1 · max 50
cursoroptionalquerystringup to 256 chars

Returns

data: OAuthGrant[]. Pass meta.cursor back as cursor for the next page.

Example requestSample
curl -X GET "https://api.billingmart.com/v1/admin/connected-apps" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

oauth clients

List

GET/v1/admin/clients

List registered OAuth clients. The client secret hash is never returned.

Scope
admin:read
Effect
Read only
MCP tool
list_oauth_clients
Retries
Safe to repeat

Parameters

List parameters
NameInTypeNotes
limitoptionalqueryintegermin 1 · max 50
cursoroptionalquerystringup to 256 chars

Returns

data: OAuthClient[]. Pass meta.cursor back as cursor for the next page.

Example requestSample
curl -X GET "https://api.billingmart.com/v1/admin/clients" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

security settings

Get

GET/v1/admin/security-settings

The workspace security settings: whether owners and admins need a second factor, whether the portal needs an email, and who may approve an agent’s actions.

Scope
admin:read
Effect
Read only
MCP tool
get_security_settings
Retries
Safe to repeat

Returns

data: TenantSecurityPolicy

Example requestSample
curl -X GET "https://api.billingmart.com/v1/admin/security-settings" \
  -H "Authorization: Bearer $BILLINGMART_API_KEY"

Object

BusinessContext

BusinessContext is computed by the server for this request, not a stored document, so no contract describes it. Its fields are the TypeScript type of the same name that the handler returns.

Object

PlanUpgradeOptions

PlanUpgradeOptions is computed by the server for this request, not a stored document, so no contract describes it. Its fields are the TypeScript type of the same name that the handler returns.

Object

AiCreditsStatus

AiCreditsStatus is computed by the server for this request, not a stored document, so no contract describes it. Its fields are the TypeScript type of the same name that the handler returns.

Object

AiCreditHistory

AiCreditHistory is computed by the server for this request, not a stored document, so no contract describes it. Its fields are the TypeScript type of the same name that the handler returns.

Object

PlanChangePreview

PlanChangePreview is computed by the server for this request, not a stored document, so no contract describes it. Its fields are the TypeScript type of the same name that the handler returns.

Object

BillingReceipt

BillingReceipt is computed by the server for this request, not a stored document, so no contract describes it. Its fields are the TypeScript type of the same name that the handler returns.

Object

ConnectionStatus

ConnectionStatus is computed by the server for this request, not a stored document, so no contract describes it. Its fields are the TypeScript type of the same name that the handler returns.

Object

SearchResult

SearchResult is computed by the server for this request, not a stored document, so no contract describes it. Its fields are the TypeScript type of the same name that the handler returns.

Object

AiProposal

What the model proposed, for every task rather than two of them. generate` returned its raw answer to a caller that stored nothing. FUNCTION-WRITTEN ONLY: create and update are `if false` for clients, and staff read is the only client access.

AiProposal fields
FieldTypeNotes
idrequiredId—
tenantrequiredTenantRef—
taskrequiredstringThe registered task name, e.g. copy.reminder, template.design.
modelrequiredstringThe model that answered — the fallback when one was used, not the primary that failed.
outputrequiredstringThe validated output, JSON-encoded. One document serves every task, so the shape is encoded rather than typed per task and the contract stays strict.
aiRawoptionalstringThe model's raw answer, verbatim and digit-masked. Masked by the gateway after the parse, never before it.
usedCacheoptionalbooleanTrue when this proposal was served from aiCache rather than the provider. A cached proposal is a real proposal; it just cost nothing.
usedFallbackoptionalbooleanTrue when the primary model failed and settings/ai.fallbackModel answered.
feedbackoptionalAiFeedback—
feedbackAtoptionalIsoTimestamp—
feedbackByoptionalIdThe uid from the verified ID token of whoever judged it — never a payload value.
createdByrequiredIdThe uid the generation was run under.
createdAtrequiredIsoTimestamp—

Object

TenantMember

Staff membership and role, kept at the ROOT rather than under the tenant so that 'which tenants does this uid belong to' is one query. The role is mirrored into a custom claim; the claim is what rules read, and this document is what the console lists.

TenantMember fields
FieldTypeNotes
idrequiredId{tenantId}_{uid}.
tenantIdrequiredId—
uidrequiredIdFirebase Auth uid.
rolerequiredRole—
businessIdsoptionalId[]Per-business assignment. Empty means every business in the tenant.
billApproveroptionalboolean. A staff member the owner or an admin has allowed to approve bills when the workspace's bill approval policy is on. Owners and admins always may. Absent means false. Set only by a function, audited.
displayNameoptionalstringUntrusted text—
emailoptionalEmail—
activerequiredboolean—
invitedAtoptionalIsoTimestamp—
acceptedAtoptionalIsoTimestamp—
revokedAtoptionalIsoTimestamp—
createdAtrequiredIsoTimestamp—
updatedAtoptionalIsoTimestamp—

Object

Invitation

A staff invitation: a capability to join the tenant as `role`, confined to `businessIds` (empty = every business). Single-use, expiring (7 days), bound to an email the acceptor must have VERIFIED. The token is shown once in the accept link and stored as an HMAC; the role never travels in the URL.

Invitation fields
FieldTypeNotes
idrequiredId—
tenantrequiredTenantRef—
emailrequiredEmailNormalised (trimmed, lowercased). The acceptor's verified email must equal it.
rolerequiredRoleNever owner — the owner role cannot be given by an invitation.
businessIdsrequiredId[]Per-business confinement copied onto the membership on accept. Empty means every business.
tokenHashrequiredstringHMAC-SHA256(pepper, token). The token itself is never stored or logged.
invitedByrequiredIdThe inviting uid, from the verified token.
expiresAtrequiredIsoTimestamp—
acceptedAtoptionalIsoTimestamp—
acceptedByUidoptionalId—
revokedAtoptionalIsoTimestamp—
revokedByoptionalId—
createdAtrequiredIsoTimestamp—
updatedAtoptionalIsoTimestamp—

Object

ApiKey

A scoped REST API key. THE KEY ITSELF IS NEVER STORED — only an HMAC of it under a server pepper, and only the prefix is displayed so a human can tell two keys apart.

ApiKey fields
FieldTypeNotes
idrequiredId—
tenantrequiredTenantRef—
namerequiredstringUntrusted textThe name a person gave the key, so a list can tell two apart.
keyHashrequiredstringHMAC-SHA256 of the secret under a pepper held in Cloud Functions secrets, so a database read alone cannot verify a key.
displayPrefixrequiredstringThe first few characters, for identification in a list. Not enough to authenticate with.
scopesrequiredScope[]—
environmentrequiredCredentialEnvironmentlive or test, fixed at creation. A test key is refused outside a tenant flagged sandbox.
ipAllowlistoptionalstring[]Optional CIDR ranges. When present, a request from any other address is refused before the key is looked up.
callsPerMinuteoptionalintegerPer-key rate limit. Absent means the tenant default (60). Enforced in the API middleware with a 429 and Retry-After.
activerequiredboolean—
stateoptionalenumDERIVED in responses, never stored.
lastUsedAtoptionalIsoTimestamp—
lastUsedIpMaskedoptionalstringMasked before storage, like every other logged identifier.
expiresAtoptionalIsoTimestamp—
revokedAtoptionalIsoTimestamp—
createdAtrequiredIsoTimestamp—
createdByoptionalId—

Object

OAuthGrant

One user's consent for one client to act inside ONE tenant with one scope set. A token is minted from a grant and dies with it: revoking the grant — console, Connected apps, Revoke — revokes every code, access and refresh token that names it, immediately, because tokens are opaque and looked up by hash.

OAuthGrant fields
FieldTypeNotes
idrequiredId—
tenantrequiredTenantRef—
clientRefrequiredIdThe oauthClients/{id} document.
clientNamerequiredstringUntrusted textSnapshot at consent.
verifiedClientrequiredbooleanSnapshot of OAuthClient.verified at consent.
subjectUidrequiredIdThe Firebase uid that consented. Must be an active member of the tenant at consent time and at every token refresh.
scopesrequiredScope[]Never wider than x-scope-ceilings.mcp; the consent screen offers nothing outside it, and the API checks again on every call.
piiSharedrequiredbooleanWhether contacts:read was granted — the one scope that sends customer email and phone to a third-party model provider. Off by default on the consent screen and listed separately in the console.
modeoptionalenumHow the connection works. Absent means ask. plan: a dry run — a write or an irreversible request is validated and answered with server-derived totals and a summary, and NOTHING is written or metered.
redirectHostoptionalstringThe host of the redirect URI used at consent, as the consent screen displayed it.
consentedAtrequiredIsoTimestamp—
lastUsedAtoptionalIsoTimestamp—
revokedAtoptionalIsoTimestamp—
revokedByoptionalIdFrom the verified ID token. Absent when the system revoked it — refresh-token reuse, member removal, tenant deletion.
narrowedAtoptionalIsoTimestampWhen the grant was last narrowed or its mode changed. A grant is narrowable and never widened: widening is a new consent.
narrowedByoptionalIdFrom the verified ID token: the person who last narrowed it — the subject, or an owner/admin.
createdAtrequiredIsoTimestamp—
updatedAtoptionalIsoTimestamp—
modeSetByoptionalId. The uid that last set the mode through setConnectionMode. Absent when the mode came from consent or narrowOAuthGrant.
modeSetAtoptionalIsoTimestamp. When setConnectionMode last wrote the mode.
droppedToPlanAtoptionalIsoTimestamp. When three rejections within 24 h dropped this connection to plan. Only a person restores it.
clientKindoptionalenumW2.
agentModeoptionalAgentModeFirst-party grants only: the person's chosen mode. mode is derived from it — auto only when this is auto and autoUntil is in the future, else ask (or plan under the three-rejection brake).
autoUntiloptionalIsoTimestampFirst-party grants only: when Auto ends by itself (8 hours after it was switched on with the second factor). Past it, the grant acts in Ask.

Object

OAuthClient

1 client the authorization server in apps/mcp knows about. ROOT collection, Admin SDK only, NO FIRESTORE RULE — like gatewayAuth, a missing rule is the correct rule. A client is not a tenant and not a person: it is the software (Claude, ChatGPT, Gemini Enterprise, a CLI) that will ask a user for a grant.

OAuthClient fields
FieldTypeNotes
idrequiredIdAlso the document id. For a CIMD client it is the SHA-256 of the metadata URL, because a URL cannot be a Firestore id.
clientIdrequiredstringThe OAuth client_id as it appears on the wire. For a CIMD client this is the https URL of its metadata document.
kindrequiredOAuthClientKind—
clientNamerequiredstringUntrusted textShown on the consent screen beside the verified badge, never instead of it.
clientUrioptionalUrl—
logoUrioptionalUrlRendered only for verified clients; an unverified logo is a phishing surface on our own consent page.
redirectUrisrequiredUrl[]`) which is matched with the port ignored so Claude Code and Gemini CLI work. com.
tokenEndpointAuthMethodrequiredTokenEndpointAuthMethod—
clientSecretHashoptionalstringHMAC-SHA256 of the client secret under the server pepper. Present only for confidential (preregistered) clients; the secret is shown once, in the console, to the tenant admin who created it.
jwksUrioptionalUrlFor private_key_jwt clients only.
softwareIdoptionalstring—
verifiedrequiredbooleanTrue only when every redirect host is in the platform allowlist.
tenantIdoptionalIdPresent for a preregistered client, which belongs to the tenant whose admin created it (the Gemini Enterprise case). Absent for dcr and cimd clients, which any tenant's user may grant.
createdAtrequiredIsoTimestamp—
lastUsedAtoptionalIsoTimestamp—
expiresAtoptionalIsoTimestampA dcr client expires 90 days after its last use, because DCR registers a fresh client on every connection and an unbounded table is a denial-of-storage surface. Preregistered clients do not expire.
revokedAtoptionalIsoTimestamp—
Next section

Clients

The people and companies you bill. Contact details come back masked unless the credential holds contacts:read.

Continue to Clients →

Try it against your sandbox

Create a bmk_test_ key in the console. It can only reach your sandbox workspace.

We use Google Analytics on our website by default to understand visits. Choose Decline to turn it off; you can change this at any time on the Cookies page. We never send Google your name, email or account. Cookie policy