Skip to main content
LaraCopilot records every call as a Call Detail Record (CDR) and matches it against a tenant-specific rate table to compute the cost. This gives you an auditable, per-second billing log that can drive invoicing, usage dashboards, and capacity planning without any external billing middleware.

Call Detail Records (CDRs)

A CDR is written at the end of every call and captures the full context needed to bill the call accurately. The fields stored on each Cdr record are:
FieldTypeDescription
tenant_idintegerTenant that owns this call record
extension_idintegerExtension that handled the call, if applicable
caller_numberstringThe originating phone number
destination_numberstringThe number that was dialled
directionstringinbound or outbound
dispositionstringOutcome of the call (e.g. ANSWERED, NO_ANSWER, BUSY)
duration_secondsintegerWall-clock length of the call in seconds
bill_secondsintegerBillable seconds after applying the rate’s billing_increment
costdecimal (4 dp)Computed cost for this call
started_atdatetimeWhen the call was connected
ended_atdatetimeWhen the call ended
duration_seconds is the actual call length. bill_seconds may differ because rates apply a billing_increment that rounds up to the nearest increment boundary (e.g. a 6-second increment means a 7-second call bills as 12 seconds).

Rates

Rates define the cost of calls to a given destination for a specific tenant. LaraCopilot matches an outbound destination_number against the rate prefix table to find the correct rate, then applies it to bill_seconds to produce cost.
FieldTypeDescription
tenant_idintegerTenant this rate applies to
prefixstringDialling prefix used to match destination numbers (e.g. 1, 44)
destinationstringHuman-readable destination name (e.g. USA, UK Landline)
cost_per_minutedecimal (4 dp)Rate charged per minute of billable time
billing_incrementintegerMinimum billing unit in seconds; calls are rounded up to this boundary
statusstringWhether the rate is active or inactive

Cost Calculation

The formula applied to each CDR is:
cost = (bill_seconds / 60) × cost_per_minute
bill_seconds is already rounded up to the nearest billing_increment before this calculation runs, so the effective minimum charge per call is:
(billing_increment / 60) × cost_per_minute
Use a billing_increment of 6 for modern telecom-style billing or 60 for simpler per-minute rounding. Smaller increments give callers a fairer cost at the expense of slightly more complex invoices.

API Reference

Retrieving CDRs

GET /api/cdrs
Returns all CDR records with their associated tenant and extension. Supports a search query parameter that filters on caller_number, destination_number, direction, and disposition.
Sample response
{
  "message": "CDRs fetched successfully.",
  "data": [
    {
      "id": 501,
      "tenant_id": 7,
      "caller_number": "+14155550100",
      "destination_number": "+14085550199",
      "direction": "outbound",
      "disposition": "ANSWERED",
      "duration_seconds": 125,
      "bill_seconds": 126,
      "cost": "0.0420",
      "started_at": "2026-04-22T09:00:00Z",
      "ended_at": "2026-04-22T09:02:05Z"
    }
  ]
}

Managing Rates

GET  /api/rates          # List all rates (supports ?search=)
POST /api/rates          # Create a new rate
GET  /api/rates/{id}     # Retrieve a single rate
PUT  /api/rates/{id}     # Update a rate
DELETE /api/rates/{id}   # Delete a rate
{
  "tenant_id": 7,
  "prefix": "1",
  "destination": "USA",
  "cost_per_minute": "0.0200",
  "billing_increment": 6,
  "status": "active"
}
Changing cost_per_minute or billing_increment on an existing rate does not retroactively recalculate historical CDRs. Old CDR costs are immutable once written.
Query GET /api/cdrs with a search filter to retrieve call records for a specific number or direction and generate usage reports for individual tenants.