Skip to content
SIP.IO
DocsStart free

Multi-Tenant & White-Label

SIP.IO is multi-tenant from the ground up, with first-class support for resellers and white-label operators. This page explains the account hierarchy and how tenancy flows through the system.

An account is a tenant. Accounts form a tree via parent_id:

  • A platform-direct account has parent_id = NULL.
  • A reseller account (is_reseller = 1) can own child accounts, brand them, and bill them.
Platform
├── Account: Acme Corp (platform-direct)
└── Account: VoiceReseller Inc. (is_reseller = 1)
├── Account: Bistro Group (white-labeled under VoiceReseller)
└── Account: City Clinic

Every tenant row in the data model carries an explicit, indexed account_id, so tenancy is never implicit: it’s a column you can see, index, and enforce.

Each account carries its own branding and defaults, which children inherit unless overridden:

FieldPurpose
brand_name, brand_domainWhite-label brand and the portal/API host for a reseller.
timezoneDefault timezone for the account (used by schedules unless a schedule overrides it).
languageDefault prompt language (one of the 16 supported languages).
voice_genderDefault narrator gender for system prompts (male / female).
default_cid_numberDefault outbound caller-ID number.
did_default_dest_kind / did_default_dest_idWhere unrouted DIDs land.

A reseller serves its own customers under its own SIP domains (sip_domain) and brand domain, so end customers never see the platform.

An account can answer on several SIP domains: its own plus white-label vanity domains. The domain is the realm used for digest authentication, so 1002@acmeA and 1002@acmeB are distinct identities even with the same extension number. Registration lookups are domain-scoped (use_domain), keeping tenants cleanly separated at the registrar.

For resellers and white-label customers who don’t want the SIP.IO brand showing up in their SIP addressing, an account can be given its own subdomain under a shared suffix, for example acme.cust.sip.io, following the same model as Twilio SIP Domains. This is not a separate feature from the SIP domains described above: a vanity realm is just another sip_domain row for the account, so it inherits the same digest-auth and domain-scoped registration behavior.

Provisioning is admin-gated (/admin/account-domain) and handles the details so a tenant can’t collide with the platform or with another tenant:

  • Label derivation. A label can be supplied explicitly (a vanity request) or, if omitted, is derived from the account name.
  • Slugify. Whatever text becomes the label is lowercased and reduced to a DNS-safe form (non-alphanumeric characters collapse to hyphens, leading/trailing hyphens trimmed, capped at 63 characters), so Acme Corp! becomes acme-corp.
  • Reserved names blocked. Platform-significant labels (api, nodes, console, realtime, sip, admin, and similar) are rejected so a tenant can’t grab a name that could be confused with platform infrastructure.
  • Uniqueness. An explicit vanity label must be free, an attempt to reuse one returns a conflict. An auto-derived label that collides is instead disambiguated automatically (a suffix from the account ID is appended) rather than failing, since the caller didn’t ask for that specific name.
  • Primary flag. A domain can be marked primary for the account; the provisioning engine treats an account’s primary sip_domain as its realm, so flipping this is what actually switches a tenant onto its vanity domain.
  • An account always keeps at least one domain: the last remaining domain on an account cannot be deleted.

The suffix itself is environment-configured (cust.sip.io in production), so the same code path also serves a separate dev suffix without any logic changes.

A vanity realm changes SIP addressing, not the TLS connection. The realm (acme.cust.sip.io) is what appears in the From/To and digest-auth identity, giving a reseller’s customers their own-looking SIP domain. It is deliberately not matched by a wildcard TLS certificate: RFC 5922 §7.2 forbids wildcard matching of SIP domain identities, so a *.cust.sip.io certificate wouldn’t be meaningful for proving the connection is genuine. In practice, provisioned phones and softphones connect over TLS/WSS to the platform’s own SBC hostname, not to the vanity realm, the SBC hostname is what the TLS certificate actually covers. The vanity domain travels inside the SIP signaling as the account’s realm; it isn’t used as the wire-level TLS endpoint. Per-domain certificates and SNI-based routing remain an option later for bring-your-own-domain or federation cases, but are not required for the common white-label case.

Tenancy isn’t just a data convention: it’s enforced at each decision point:

  • /auth resolves the device by (auth_username, realm) and returns the owning account_id; the SIP signaling layer binds that account context to the registration.
  • /route scopes every lookup by account_id: DIDs, extensions, outbound routes, transforms, and caller-ID rules are all matched within the tenant.
  • stateful edge objects are per-account. The PresenceEngine and BalanceLedger are addressed by account_id, so one tenant’s presence, ACD, CAC counters, and wallet are physically isolated in their own object.

Each account has its own concurrency ceilings (max_in, max_out, max_dialer) and its own CAC counters in its PresenceEngine. Spend is governed by a separate retail wallet (BalanceLedger) plus the wholesale carrier’s authoritative balance, so one tenant can’t consume another’s capacity or budget.

The account tree carries the billing relationship: a child account’s usage rolls up to its reseller parent. Wholesale termination and balance are handled by the carrier integration per subaccount, while the platform tracks the retail relationship.

  • Put each end customer in its own account; give resellers is_reseller = 1 and their own brand_domain.
  • Set the account’s timezone, language, and voice_gender once, and schedules and prompts inherit them.
  • Use per-account max_* ceilings as the first line of capacity isolation; layer rate rules on top for finer control.