Skip to content

Best time to call: contact-rate ranking of the dialing feed ​

Español: Mejor hora para llamar.

This guide explains how the platform uses the historical contact rate by weekday and local hour to order the leads it dials. It is configuration and behavior only; it adds no API route.

Availability ​

CapabilityAvailability
Best-hour ranking of the dialing feed, on by defaultPublished in core v0.101.0
best_time_ranking_enabled switchPublished in core v0.101.0

The ranking and its switch entered core in v0.101.0 (core#1979, ADR #238 in core's ADR.md); a core older than that does not have them.

What it does ​

When the dialer picks the next leads to call, it already has a batch of candidates. The ranking reorders that batch by how well the lead's current local weekday and hour have contacted people before:

text
weight = clamp(cell_rate / level_rate, 0.5, 1.5)
  • cell_rate is the contact rate of the lead's local weekday and hour.
  • level_rate is the average contact rate of the same level.
  • The weight is clamped to [0.5, 1.5], so it is a nudge to the order, not a verdict: one good number is not buried by a weak hour, and an hour with a few lucky answers cannot lift a lead past the whole batch.

The history comes from call_attempts, through the same query as the GET /v1/stats/contact-windows report, so the report and the ranking cannot disagree. A cell speaks only once it holds at least contact_window_min_attempts attempts (the same floor as that report). The first level that does speak wins: the campaign's own history, then the tenant's whole portfolio, then no data. With no data the weight is 1.0 and the order is exactly the order the feed always had.

On by default ​

The ranking is on for every tenant with no action needed. A platform operator can switch it off per tenant with best_time_ranking_enabled; the feed then returns, byte for byte, to its previous order. The key is independent of contact_score_ranking_enabled, which stays off by default.

The weight only orders leads inside the batch that was already allowed. It does not change which leads are candidates or the hours they may be dialed in. Every lead still has to pass the pre-dial compliance gate (quiet hours [08:00, 21:00) in every candidate time zone, the 7-in-7 rule and the state matrix). A lead in a weak hour moves down the batch; it does not leave it, and an hour the gate would refuse is never rewarded:

  • A lead the gate will block right now (an unresolvable number or time zone, or any candidate zone outside [08:00, 21:00)) weighs the floor, 0.5.
  • When a number has several candidate zones, all inside the window, the weight is 1.0: the rule does not guess which zone is correct.

Not an opaque model ​

The shipped ranking is the fixed formula above, computed from counts you can read in GET /v1/stats/contact-windows. It is not a learned model. The engine sits behind an interface that allows a different method to be plugged in per tenant later, but none ships today.

Cost and refresh ​

The history is a 90-day aggregation of call_attempts per tenant, cached and refreshed off the dialing tick. A failure or an empty cache yields weight 1.0, so ranking can never delay or block a dial.

Nothing in these docs is legal advice — always confirm compliance posture with your own counsel.