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.
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
Field
Type
Notes
businessIdrequired
id
—
intentrequired
enum
One of add, change
keyoptional
string
up to 64 chars
labelrequired
string
up to 120 chars
rateBasisrequired
enum
One of fixed, hourly, daily, weekly, monthly, perUnit, perMile, perKilometre, percentage
defaultUnitPriceoptional
object
—
defaultUnitPrice.minorUnitsrequired
integer
—
defaultUnitPrice.currencyrequired
Currency
—
defaultRateBasisPointsoptional
integer
min -10000000 · max 10000000
taxTreatmentoptional
enum
One 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.
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.
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.
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
Name
In
Type
Notes
kindoptional
query
enum
One of grant, purchase, usage, adjustment, reversal, expiry, allowance
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.
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.
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.
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
Name
In
Type
Notes
qrequired
query
string
up to 100 chars
typeoptional
query
enum
One of invoice, estimate, client, job, vendor
limitoptional
query
integer
min 1 · max 25
cursoroptional
query
string
up 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
Name
In
Type
Notes
limitoptional
query
integer
min 1 · max 50
cursoroptional
query
string
up to 256 chars
taskoptional
query
string
up 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
Field
Type
Notes
businessIdrequired
id
—
hintrequired
string
at 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.
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
Name
In
Type
Notes
recurringIdrequired
path
id
—
Returns
data: object
Errors this route can answer besides the shared ones: AI_DISABLED, AI_CAP_REACHED, AI_CREDITS_EXHAUSTED.
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
Name
In
Type
Notes
businessIdrequired
path
id
—
Request body
JSON. Money is an integer count of minor units beside its currency; quantities are thousandths.
Draft dunning ladder request body
Field
Type
Notes
toneoptional
enum
One of friendly, neutral, firm
Returns
data: object
Errors this route can answer besides the shared ones: AI_DISABLED, AI_CAP_REACHED, AI_CREDITS_EXHAUSTED.
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
Name
In
Type
Notes
jobIdrequired
path
id
—
Request body
JSON. Money is an integer count of minor units beside its currency; quantities are thousandths.
Job summary request body
Field
Type
Notes
refreshoptional
boolean
—
Returns
data: object
Errors this route can answer besides the shared ones: NOT_FOUND, AI_DISABLED, AI_CAP_REACHED, AI_CREDITS_EXHAUSTED.
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
Name
In
Type
Notes
jobIdrequired
path
id
—
Request body
JSON. Money is an integer count of minor units beside its currency; quantities are thousandths.
Job draft note request body
Field
Type
Notes
instructionoptional
string
up 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.
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
Name
In
Type
Notes
jobIdrequired
path
id
—
Request body
JSON. Money is an integer count of minor units beside its currency; quantities are thousandths.
Job draft message request body
Field
Type
Notes
channelrequired
enum
One of email, sms
instructionoptional
string
up 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.
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
Name
In
Type
Notes
jobIdrequired
path
id
—
Returns
data: object
Errors this route can answer besides the shared ones: NOT_FOUND, PERMISSION_DENIED, AI_DISABLED, AI_CAP_REACHED, AI_CREDITS_EXHAUSTED.
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
Field
Type
Notes
descriptionrequired
string
at 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.
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.
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
Name
In
Type
Notes
limitoptional
query
integer
min 1 · max 50
cursoroptional
query
string
up 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
Name
In
Type
Notes
limitoptional
query
integer
min 1 · max 50
cursoroptional
query
string
up 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
Name
In
Type
Notes
limitoptional
query
integer
min 1 · max 50
cursoroptional
query
string
up 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
Name
In
Type
Notes
limitoptional
query
integer
min 1 · max 50
cursoroptional
query
string
up 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
Name
In
Type
Notes
limitoptional
query
integer
min 1 · max 50
cursoroptional
query
string
up 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
Field
Type
Notes
idrequired
Id
—
tenantrequired
TenantRef
—
taskrequired
string
The registered task name, e.g. copy.reminder, template.design.
modelrequired
string
The model that answered — the fallback when one was used, not the primary that failed.
outputrequired
string
The validated output, JSON-encoded. One document serves every task, so the shape is encoded rather than typed per task and the contract stays strict.
aiRawoptional
string
The model's raw answer, verbatim and digit-masked. Masked by the gateway after the parse, never before it.
usedCacheoptional
boolean
True when this proposal was served from aiCache rather than the provider. A cached proposal is a real proposal; it just cost nothing.
usedFallbackoptional
boolean
True when the primary model failed and settings/ai.fallbackModel answered.
feedbackoptional
AiFeedback
—
feedbackAtoptional
IsoTimestamp
—
feedbackByoptional
Id
The uid from the verified ID token of whoever judged it — never a payload value.
createdByrequired
Id
The uid the generation was run under.
createdAtrequired
IsoTimestamp
—
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
Field
Type
Notes
idrequired
Id
{tenantId}_{uid}.
tenantIdrequired
Id
—
uidrequired
Id
Firebase Auth uid.
rolerequired
Role
—
businessIdsoptional
Id[]
Per-business assignment. Empty means every business in the tenant.
billApproveroptional
boolean
. 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.
displayNameoptional
string
Untrusted text—
emailoptional
Email
—
activerequired
boolean
—
invitedAtoptional
IsoTimestamp
—
acceptedAtoptional
IsoTimestamp
—
revokedAtoptional
IsoTimestamp
—
createdAtrequired
IsoTimestamp
—
updatedAtoptional
IsoTimestamp
—
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
Field
Type
Notes
idrequired
Id
—
tenantrequired
TenantRef
—
emailrequired
Email
Normalised (trimmed, lowercased). The acceptor's verified email must equal it.
rolerequired
Role
Never owner — the owner role cannot be given by an invitation.
businessIdsrequired
Id[]
Per-business confinement copied onto the membership on accept. Empty means every business.
tokenHashrequired
string
HMAC-SHA256(pepper, token). The token itself is never stored or logged.
invitedByrequired
Id
The inviting uid, from the verified token.
expiresAtrequired
IsoTimestamp
—
acceptedAtoptional
IsoTimestamp
—
acceptedByUidoptional
Id
—
revokedAtoptional
IsoTimestamp
—
revokedByoptional
Id
—
createdAtrequired
IsoTimestamp
—
updatedAtoptional
IsoTimestamp
—
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
Field
Type
Notes
idrequired
Id
—
tenantrequired
TenantRef
—
namerequired
string
Untrusted textThe name a person gave the key, so a list can tell two apart.
keyHashrequired
string
HMAC-SHA256 of the secret under a pepper held in Cloud Functions secrets, so a database read alone cannot verify a key.
displayPrefixrequired
string
The first few characters, for identification in a list. Not enough to authenticate with.
scopesrequired
Scope[]
—
environmentrequired
CredentialEnvironment
live or test, fixed at creation. A test key is refused outside a tenant flagged sandbox.
ipAllowlistoptional
string[]
Optional CIDR ranges. When present, a request from any other address is refused before the key is looked up.
callsPerMinuteoptional
integer
Per-key rate limit. Absent means the tenant default (60). Enforced in the API middleware with a 429 and Retry-After.
activerequired
boolean
—
stateoptional
enum
DERIVED in responses, never stored.
lastUsedAtoptional
IsoTimestamp
—
lastUsedIpMaskedoptional
string
Masked before storage, like every other logged identifier.
expiresAtoptional
IsoTimestamp
—
revokedAtoptional
IsoTimestamp
—
createdAtrequired
IsoTimestamp
—
createdByoptional
Id
—
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
Field
Type
Notes
idrequired
Id
—
tenantrequired
TenantRef
—
clientRefrequired
Id
The oauthClients/{id} document.
clientNamerequired
string
Untrusted textSnapshot at consent.
verifiedClientrequired
boolean
Snapshot of OAuthClient.verified at consent.
subjectUidrequired
Id
The Firebase uid that consented. Must be an active member of the tenant at consent time and at every token refresh.
scopesrequired
Scope[]
Never wider than x-scope-ceilings.mcp; the consent screen offers nothing outside it, and the API checks again on every call.
piiSharedrequired
boolean
Whether 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.
modeoptional
enum
How 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.
redirectHostoptional
string
The host of the redirect URI used at consent, as the consent screen displayed it.
consentedAtrequired
IsoTimestamp
—
lastUsedAtoptional
IsoTimestamp
—
revokedAtoptional
IsoTimestamp
—
revokedByoptional
Id
From the verified ID token. Absent when the system revoked it — refresh-token reuse, member removal, tenant deletion.
narrowedAtoptional
IsoTimestamp
When the grant was last narrowed or its mode changed. A grant is narrowable and never widened: widening is a new consent.
narrowedByoptional
Id
From the verified ID token: the person who last narrowed it — the subject, or an owner/admin.
createdAtrequired
IsoTimestamp
—
updatedAtoptional
IsoTimestamp
—
modeSetByoptional
Id
. The uid that last set the mode through setConnectionMode. Absent when the mode came from consent or narrowOAuthGrant.
modeSetAtoptional
IsoTimestamp
. When setConnectionMode last wrote the mode.
droppedToPlanAtoptional
IsoTimestamp
. When three rejections within 24 h dropped this connection to plan. Only a person restores it.
clientKindoptional
enum
W2.
agentModeoptional
AgentMode
First-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).
autoUntiloptional
IsoTimestamp
First-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
Field
Type
Notes
idrequired
Id
Also the document id. For a CIMD client it is the SHA-256 of the metadata URL, because a URL cannot be a Firestore id.
clientIdrequired
string
The OAuth client_id as it appears on the wire. For a CIMD client this is the https URL of its metadata document.
kindrequired
OAuthClientKind
—
clientNamerequired
string
Untrusted textShown on the consent screen beside the verified badge, never instead of it.
clientUrioptional
Url
—
logoUrioptional
Url
Rendered only for verified clients; an unverified logo is a phishing surface on our own consent page.
redirectUrisrequired
Url[]
`) which is matched with the port ignored so Claude Code and Gemini CLI work. com.
tokenEndpointAuthMethodrequired
TokenEndpointAuthMethod
—
clientSecretHashoptional
string
HMAC-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.
jwksUrioptional
Url
For private_key_jwt clients only.
softwareIdoptional
string
—
verifiedrequired
boolean
True only when every redirect host is in the platform allowlist.
tenantIdoptional
Id
Present 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.
createdAtrequired
IsoTimestamp
—
lastUsedAtoptional
IsoTimestamp
—
expiresAtoptional
IsoTimestamp
A 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.
revokedAtoptional
IsoTimestamp
—
Next section
Clients
The people and companies you bill. Contact details come back masked unless the credential holds contacts:read.
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