v1.0 Dashboard Public Profile GitHub
✅ Complete (Core) Phase 16

Phase 16 — Telephony Number Management

A complete DID marketplace inside KaiVox — browse, purchase, manage, and auto-renew phone numbers from Vobiz (India) and Twilio (Global), with full billing lifecycle management.

What It Does

Tenants never need to leave KaiVox to manage their phone numbers. They can browse available numbers by region, purchase with one click (deducted from their wallet), and have webhook URLs auto-configured. Monthly billing runs automatically. Numbers can be released when no longer needed.

Key Routes

URLDescription
GET /phone-numbersMy Numbers — list with stats cards, status badges, capabilities
GET /phone-numbers/marketplaceDID Marketplace — browse Vobiz + Twilio numbers
GET /phone-numbers/marketplace?provider=vobizBrowse Vobiz Indian numbers
GET /phone-numbers/marketplace?provider=twilioBrowse Twilio global numbers
POST /phone-numbers/purchasePurchase a number (wallet deduction + webhook auto-config)
GET /phone-numbers/{id}Number detail — metadata, billing history
PUT /phone-numbers/{id}Edit label and caller ID name
POST /phone-numbers/{id}/releaseRelease number — provider API call + status=released

Key Files

TypePath
Serviceapp/Services/PhoneNumberService.php — purchase, release, runMonthlyBilling()
Controllerapp/Http/Controllers/PhoneNumbersController.php
Modelapp/Models/PhoneNumber.php
Modelapp/Models/PhoneNumberBilling.php
Commandapp/Console/Commands/BillPhoneNumbers.phpphone-numbers:bill
Tablephone_numbers — tenant_id, number, provider, provider_number_id, number_type, region, area_code, capabilities, setup_fee, monthly_fee, status, purchased_at, last_billed_at, next_billing_at, caller_id_name, label
Tablephone_number_billing — phone_number_id, billing_period, amount, status (paid/failed), failure_reason

Number Capabilities

CapabilityIconDescription
Voice📞Can receive and make voice calls
SMS💬Can send and receive SMS
WhatsApp🟢WhatsApp-enabled number (Twilio only)

Number Status States

  • active — number is in use and billing is current
  • suspended — insufficient wallet balance to renew
  • released — number released back to provider

Purchase Flow

Tenant browses marketplace → selects a number → clicks "Purchase"
        ↓
Purchase modal shows: number, setup fee, monthly rent, wallet balance check
        ↓
If wallet insufficient → "Confirm" button disabled, "Top Up Wallet" shown
        ↓
Tenant confirms purchase
        ↓
PhoneNumberService::purchase($tenant, $numberData)
  1. Duplicate number guard (prevents re-purchasing same number)
  2. Provider API call (Vobiz or Twilio) to provision number
  3. Auto-configure webhook URLs (answer/hangup) for tenant slug
  4. Deduct setup_fee + first month's monthly_fee from wallet
  5. Create phone_numbers record with status=active
  6. Create initial phone_number_billing record (paid)
        ↓
Number appears in "My Numbers" with webhooks pre-configured

Monthly Billing

The BillPhoneNumbers artisan command runs daily at 02:00 AM via the Laravel scheduler:

php artisan phone-numbers:bill

# Equivalent to:
PhoneNumberService::runMonthlyBilling()

# Logic:
foreach (PhoneNumber::dueBilling()->get() as $number) {
    if ($number->tenant->wallet_balance >= $number->monthly_fee) {
        // Deduct monthly_fee from wallet
        // Update last_billed_at + next_billing_at
        // Create phone_number_billing record (status=paid)
    } else {
        // Create phone_number_billing record (status=failed)
        // Set number status = suspended
        // Low balance automation trigger fires
    }
}

Mock Fallback Data

When Vobiz credentials are not configured in Super Admin → Platform Settings, or Twilio credentials are missing from .env, the marketplace shows mock data for testing:

  • 6 Vobiz Indian DIDs (Mumbai, Delhi, Bangalore area codes)
  • 4 Twilio US numbers (New York, Los Angeles area codes)

This allows the full purchase UI flow to be tested without real provider accounts.

Caller ID Name

Each number can have a "Caller ID Name" (max 15 characters) — shown to people you call. Example: "CITY CARE CLNC". This is set at purchase and editable from the number detail page.

What's Complete

  • DID Marketplace: browse Vobiz (India) and Twilio (Global) with region/area code filters
  • Provider tabs in marketplace UI
  • Mock fallback data when API credentials missing
  • Purchase modal with cost breakdown and wallet balance check
  • Auto-configure webhook URLs on purchase
  • Wallet deduction on purchase (setup fee + first month)
  • Duplicate number guard
  • My Numbers list with stats cards, status badges, capability icons, next billing date
  • Number detail page with metadata and billing history (last 24 records)
  • Edit label and caller ID name (max 15 chars)
  • Release number flow
  • Monthly billing runner + BillPhoneNumbers command registered in scheduler at 02:00
  • PhoneNumber model with dueBilling scope, status/type/capability accessors
  • Phone Numbers nav item in sidebar (Operations section)

What's Deferred

  • Email/notification before billing date (needs email delivery unblocked)
  • Prorated billing on mid-month purchase
  • Super Admin: platform-wide DID inventory overview
  • Number porting (bring your own number)
  • Multi-number routing (route by time-of-day, location)