Wholesale Quick Start

This section guides you through the basic Wholesale module setup and your first successful call in under 10 minutes.

1. Requirements

ItemRequirement
RustPBX version≥ 0.4.4, compiled with --features commerce,wholesale
DatabaseMySQL 8.0+ or PostgreSQL 14+ (SQLite is not supported — Wholesale requires concurrent writes and transactions)
DiskReserve 100GB+/month for CDR storage (estimate based on call volume)
Memory≥ 4GB (rate decks and routing Tries are loaded into memory)

2. Enable Wholesale

Enable the addon in the [proxy] section of config.toml:

[proxy]
addons = ["wholesale"]

# Wholesale-specific configuration
[proxy.wholesale]
# Route result cache
route_cache_capacity = 10000
route_cache_ttl_secs = 30

# Circuit breaker defaults
circuit_breaker_failure_threshold = 5
circuit_breaker_open_duration_secs = 30

3. Database Initialization

Wholesale automatically runs 30+ migrations on startup, creating the following core tables:

TablePurpose
rustpbx_tenantsTenants (customers)
wholesale_rate_decksRate decks (buy/sell)
wholesale_ratesRate entries
wholesale_routing_profilesRouting profiles
wholesale_routing_profile_itemsRouting rules
wholesale_tenant_trunksTenant trunk bindings
wholesale_trunk_configsTrunk Wholesale configuration
wholesale_cdrsCall detail records
wholesale_billsBills

4. Minimal Setup Workflow

Step 1: Create a Carrier Trunk

Add a carrier SIP trunk via the web console under Wholesale → Trunk Management or in config/trunks/:

# config/trunks/carrier_a.toml
[[trunk]]
name = "carrier-a"
dest = "sip:10.0.1.100:5060"
direction = "outbound"
codec = ["pcmu", "pcma", "g729"]
max_calls = 100

In the Wholesale console, configure this trunk with:

  • An associated buy rate deck
  • Circuit breaker enabled/disabled

Step 2: Create Rate Decks

Wholesale → Rate Deck Management → Create New:

  • Create a Buy Deck: the carrier’s cost price
  • Create a Sell Deck: the sales price for customers

Add rate entries (CSV bulk import is supported):

PrefixRate (per minute)Min DurationBilling Increment
860.0566
86100.0366
10.0866

Rate matching uses longest prefix match (Trie). 8610 is more specific than 86.

Step 3: Create a Routing Profile

Wholesale → Routing Profiles → Create New:

Add a routing rule:

  • Match prefix: 86
  • Trunk: carrier-a
  • Priority: 10
  • Weight: 100

Step 4: Create a Tenant

Wholesale → Tenant Management → Create New:

  • Name: Customer A
  • Initial balance: 1000.00
  • Associated sell rate deck
  • Associated routing profile
  • Configure trunk binding (inbound IP ACL or Token authentication)

Step 5: Verify

Use a SIP softphone or SIPp to simulate a call from the tenant side. Check:

  1. Whether the call establishes normally
  2. Whether a CDR is generated correctly (Wholesale → CDR Management)
  3. Whether the tenant balance is deducted correctly

5. Authentication Methods

Wholesale supports two inbound authentication methods for tenants:

MethodConfigurationUse Case
IP ACLsource_ips in the tenant trunk bindingGateways/softswitches with fixed IPs
X-Wholesale-TokenHMAC-SHA256 signed TokenDynamic IPs or higher security requirements

Token format: token_id|timestamp|tenant_id|caller|callee|signature

6. Next Steps