Overview
The platform credit billing system converts all external provider costs into a common credit system, applies configurable margin at the cost-event level, deducts credits where external costs are incurred, and provides superadmin-only cost-vs-sale visibility.Pricing Model
Default configuration stored inplatform_billing_config:
For each external cost event:
Database Schema
Core Tables
Analytics View
Atomic Debit Function
record_external_cost_event(...) performs all billing writes in one transaction:
1
Load Defaults
Load
credit_value_usd and margin_multiplier from billing config.2
Ensure Account
Ensure organization billing account exists (create if not).
3
Lock Wallet
Lock wallet row with
FOR UPDATE for concurrency safety.4
Calculate
Calculate
charged_usd and credits_burned.5
Update Wallet
Update wallet balances and counters.
6
Record Cost Event
Insert into
external_cost_events.7
Record Ledger Entry
Insert matching row in
organization_credit_ledger.8
Return Result
Return billing result payload (event id, burn, charged, balance after).
This function is the canonical low-level billing entry point. All provider cost recording must go through this function.
Current Coverage Matrix
Mandatory Integration Contract
Requirements
- Identify cost-incurring operations at the provider boundary
- Record costs using
record_external_cost_event(...)in the same execution path - Pass
organizationId(required) anduserId(when available) to the billing call - Store normalized metadata:
provider,operation,reference_type,reference_id - Define failure policy:
- Strict: fail request if billing write fails
- Best-effort: log and continue (only for non-critical async paths)
- Add tests verifying:
- External cost event row is created
- Ledger row is created
- Expected margin/credit conversion is applied
New Knowledge Base Connector Checklist
- Connector jobs include
organizationIdanduserIdin job payload - Embedding generation routed through
EmbeddingService(billing is automatic) - If connector calls paid third-party APIs, add a billing event for that API call
- Set connector-specific
reference_typevalues (e.g.,kb_connector_sync) - Add integration tests for indexing success and retry/idempotency
New Publish Destination Checklist
- Treat outbound provider calls as billable operations
- Add billing calls at the destination adapter layer (not only in route handlers)
- Use operation names mapping to destination actions (
publish_send,publish_webhook) - Include destination/channel IDs in metadata for auditing
- Add dashboard-facing provider normalization for readable superadmin reporting
Superadmin Reporting
Frontend:apps/web/src/components/billing/PlatformBillingDashboard.tsx — visible only when user.isSuperAdmin === true.
Response includes: totals, daily trend, provider rollup, organization rollup, and plan mix.
Service Integrations
- Bot Service
- Knowledge Service
- Realtime Audio
- File Storage
bot.service.ts: Chat cost calculated from synced model pricing, callsBillingRepository.recordExternalCost(...)after each completionbilling.repository.ts: Wrapsrecord_external_cost_event, exposesgetPlatformSummary()for dashboard
Access Control
Superadmin emails configured via:- Backend:
PLATFORM_SUPERADMIN_EMAILS - Frontend:
NEXT_PUBLIC_PLATFORM_SUPERADMIN_EMAILS
403.
Operational Notes
- Migration
014_platform_credit_billing.sqlis idempotent (safe to re-run) - Keep gateway proxy from forwarding
content-lengthwhen body is reserialized - Billing function uses row locking for consistent wallet debits under concurrency
Future Extensions
- Stripe checkout + invoice sync into
organization_credit_ledger - Auto top-up workers based on wallet thresholds
- Plan upgrade/downgrade lifecycle automation
- Hard balance floor and configurable overage behavior per plan

