Overview
BoxBilling uses 40 SQLAlchemy models organized into logical domains. All entities (except the legacyItem) use UUID primary keys and include audit timestamps (created_at, updated_at). Monetary amounts use Numeric(12,4) for precision.
Entity relationship diagram
Organization & accounts
Organization
The root tenant entity. All resources are scoped to an organization.| Column | Type | Description |
|---|---|---|
id | UUID | Primary key |
name | String(255) | Organization name |
default_currency | String(3) | Default currency (e.g. USD) |
timezone | String(50) | Default timezone |
net_payment_term | Integer | Days until invoice due (default: 30) |
invoice_grace_period | Integer | Grace period days (default: 0) |
document_number_prefix | String(20) | Invoice number prefix |
email, legal_name, address_* | String | Organization details |
Customer
| Column | Type | Description |
|---|---|---|
id | UUID | Primary key |
organization_id | UUID | FK → organizations |
external_id | String(255) | Unique external identifier |
name | String(255) | Customer name |
email | String(255) | Contact email |
currency | String(3) | Billing currency |
billing_metadata | JSON | Custom key-value metadata |
net_payment_term | Integer | Override org default |
ApiKey
| Column | Type | Description |
|---|---|---|
id | UUID | Primary key |
organization_id | UUID | FK → organizations |
key_hash | String(255) | SHA-256 hash of the API key |
key_prefix | String(20) | Display prefix (e.g. bxb_live_abc...) |
status | String(50) | active or revoked |
expires_at | DateTime | Optional expiration |
last_used_at | DateTime | Last successful auth |
Subscription & billing
Plan
| Column | Type | Description |
|---|---|---|
id | UUID | Primary key |
code | String(255) | Unique plan code |
name | String(255) | Display name |
interval | String(20) | weekly, monthly, quarterly, yearly |
amount_cents | Integer | Base subscription fee |
currency | String(3) | Plan currency |
trial_period_days | Integer | Default trial length |
Subscription
| Column | Type | Description |
|---|---|---|
id | UUID | Primary key |
external_id | String(255) | Unique external identifier |
customer_id | UUID | FK → customers |
plan_id | UUID | FK → plans |
status | String(20) | pending, active, canceled, terminated |
billing_time | String(20) | calendar or anniversary |
pay_in_advance | Boolean | Bill at start of period |
trial_period_days | Integer | Trial duration |
previous_plan_id | UUID | Pending downgrade target |
started_at | DateTime | Activation timestamp |
ending_at | DateTime | Termination timestamp |
canceled_at | DateTime | Cancellation timestamp |
Commitment
Minimum spend commitments attached to plans.| Column | Type | Description |
|---|---|---|
plan_id | UUID | FK → plans |
commitment_type | String(50) | minimum_commitment |
amount_cents | Numeric(12,4) | Minimum amount |
Usage & metrics
BillableMetric
| Column | Type | Description |
|---|---|---|
code | String(255) | Unique metric code |
name | String(255) | Display name |
aggregation_type | String(20) | count, sum, max, unique_count, weighted_sum, latest, custom |
field_name | String(255) | Event property to aggregate |
recurring | Boolean | Persists across billing periods |
expression | Text | Custom aggregation expression |
rounding_function | String(10) | round, ceil, floor |
BillableMetricFilter
Filters that segment events by property values.| Column | Type | Description |
|---|---|---|
billable_metric_id | UUID | FK → billable_metrics |
key | String(255) | Property key to filter on |
values | JSON | Allowed values |
(billable_metric_id, key)
Event
| Column | Type | Description |
|---|---|---|
transaction_id | String(255) | Unique idempotency key |
external_customer_id | String(255) | Customer reference |
code | String(255) | Billable metric code |
timestamp | DateTime | Event timestamp |
properties | JSON | Event-specific data |
(external_customer_id, code, timestamp)
DailyUsage
Pre-aggregated daily usage for performance optimization.| Column | Type | Description |
|---|---|---|
subscription_id | UUID | FK → subscriptions |
billable_metric_id | UUID | FK → billable_metrics |
usage_date | Date | Aggregation date |
usage_value | Numeric(12,4) | Aggregated value |
events_count | Integer | Event count |
Charges & pricing
Charge
Links a billable metric to a plan with a pricing model.| Column | Type | Description |
|---|---|---|
plan_id | UUID | FK → plans (CASCADE) |
billable_metric_id | UUID | FK → billable_metrics |
charge_model | String(30) | Pricing model type |
properties | JSON | Model-specific config |
standard, graduated, volume, package, percentage, graduated_percentage, custom, dynamic
ChargeFilter / ChargeFilterValue
Override charge properties for specific filter values (e.g., different pricing per region).Invoicing
Invoice
| Column | Type | Description |
|---|---|---|
invoice_number | String(50) | Unique invoice number |
customer_id | UUID | FK → customers |
subscription_id | UUID | FK → subscriptions (nullable) |
status | String(20) | draft, finalized, paid, voided |
invoice_type | String(30) | subscription, add_on, credit, one_off, progressive_billing |
subtotal | Numeric(12,4) | Pre-tax amount |
tax_amount | Numeric(12,4) | Total tax |
total | Numeric(12,4) | Final amount |
prepaid_credit_amount | Numeric(12,4) | Wallet credits applied |
coupons_amount_cents | Numeric(12,4) | Coupon discounts applied |
line_items | JSON | Line item details |
Fee
Individual charge line items on an invoice.| Column | Type | Description |
|---|---|---|
invoice_id | UUID | FK → invoices |
charge_id | UUID | FK → charges (nullable) |
customer_id | UUID | FK → customers |
fee_type | String(20) | charge, subscription, add_on, credit, commitment |
amount_cents | Numeric(12,4) | Fee amount |
units | Numeric(12,4) | Usage units |
events_count | Integer | Events counted |
payment_status | String(20) | pending, succeeded, failed, refunded |
InvoiceSettlement
Tracks how invoices are paid (multiple settlement types per invoice).| Column | Type | Description |
|---|---|---|
invoice_id | UUID | FK → invoices |
settlement_type | String(20) | payment, credit_note, wallet_credit |
source_id | UUID | Reference to payment/credit note/wallet |
amount_cents | Numeric(12,4) | Amount settled |
CreditNote / CreditNoteItem
| Column | Type | Description |
|---|---|---|
number | String(50) | Unique (e.g. CN-20250214-0001) |
invoice_id | UUID | FK → invoices |
status | String(20) | draft, finalized |
reason | String(30) | duplicated_charge, order_change, etc. |
credit_amount_cents | Numeric(12,4) | Available credit |
balance_amount_cents | Numeric(12,4) | Remaining credit |
Payments
Payment
| Column | Type | Description |
|---|---|---|
invoice_id | UUID | FK → invoices |
customer_id | UUID | FK → customers |
amount | Numeric(12,4) | Payment amount |
status | String(20) | pending, processing, succeeded, failed, refunded, canceled |
provider | String(50) | stripe, manual, ucp, gocardless, adyen |
provider_payment_id | String(255) | External payment reference |
PaymentRequest / PaymentRequestInvoice
Manual payment requests linking multiple invoices for dunning campaigns.Wallets
Wallet
| Column | Type | Description |
|---|---|---|
customer_id | UUID | FK → customers |
status | String(20) | active, terminated |
balance_cents | Numeric(12,4) | Available balance |
credits_balance | Numeric(12,4) | Credit units |
rate_amount | Numeric(12,4) | Credits-to-cents conversion rate |
priority | Integer | Consumption priority (lower = first) |
expiration_at | DateTime | Optional expiration |
WalletTransaction
| Column | Type | Description |
|---|---|---|
wallet_id | UUID | FK → wallets |
transaction_type | String(20) | inbound, outbound |
source | String(20) | manual, interval, threshold |
amount | Numeric(12,4) | Transaction amount |
invoice_id | UUID | FK → invoices (for consumption) |
Discounts
Coupon
| Column | Type | Description |
|---|---|---|
code | String(255) | Unique coupon code |
coupon_type | String(20) | fixed_amount, percentage |
frequency | String(20) | once, recurring, forever |
reusable | Boolean | Can be applied to multiple customers |
status | String(20) | active, terminated |
AddOn
One-time charges applied to customers.| Column | Type | Description |
|---|---|---|
code | String(255) | Unique add-on code |
amount_cents | Numeric(12,4) | Default price |
Taxes
Tax
| Column | Type | Description |
|---|---|---|
code | String(255) | Unique tax code |
rate | Numeric(5,4) | Tax rate (e.g. 0.0875 for 8.75%) |
applied_to_organization | Boolean | Default org-wide tax |
AppliedTax
Polymorphic association — can be applied to any entity type.| Column | Type | Description |
|---|---|---|
tax_id | UUID | FK → taxes |
taxable_type | String(50) | Entity type (e.g. customer, plan) |
taxable_id | UUID | Entity ID |
tax_amount_cents | Numeric(12,4) | Calculated amount |
Integrations
Integration
| Column | Type | Description |
|---|---|---|
integration_type | String(30) | payment_provider, accounting, crm, tax |
provider_type | String(50) | stripe, netsuite, xero, hubspot, salesforce, etc. |
settings | JSON | Provider-specific configuration |
status | String(20) | active, inactive, error |
(organization_id, provider_type) — one integration per provider per org.
Webhooks
WebhookEndpoint
| Column | Type | Description |
|---|---|---|
url | String(2048) | Delivery URL |
signature_algo | String(50) | Signature algorithm (default: hmac) |
status | String(50) | active or inactive |
Webhook
| Column | Type | Description |
|---|---|---|
webhook_endpoint_id | UUID | FK → webhook_endpoints |
webhook_type | String(100) | Event type (e.g. invoice.finalized) |
payload | JSON | Event payload |
status | String(50) | pending, succeeded, failed |
retries | Integer | Delivery attempts |
http_status | Integer | Last response status code |
Design patterns
- UUID primary keys on all models for distributed ID generation
- Numeric(12,4) for monetary amounts — 4 decimal places of precision
- Organization isolation via
organization_idforeign key on all tenant-scoped models - Polymorphic associations for
AppliedTaxandIntegrationMapping - Soft deletes via status columns rather than row deletion
- JSON columns for flexible storage (properties, settings, metadata, line_items)