Skip to content
← Blog

Compliance

TRAI, DND and the 9-to-9 Window: What Automated Calling in India Has to Obey

DND scrubbing and the TCCCPR calling window decide whether an outbound campaign is lawful. What they require, and where implementations quietly get them wrong.

28 August 2026 · 8 min read

Most conversations about automated calling in India start with the model and end with the voice. The two rules that actually decide whether a campaign is lawful get mentioned last, if at all — and they are not model problems. They are dialler problems, and a platform either handles them at the right moment or it does not.

This is not legal advice, and we are not a law firm. It is a description of what the rules require and how a dialler has to be built to respect them, written by people who had to build one. Take the compliance question itself to counsel.

Rule one: the calling window is nine to nine, in the recipient's time

The Telecom Commercial Communications Customer Preference Regulations — TCCCPR, the framework TRAI administers — sets a window for commercial calls of 09:00 to 21:00. The part implementations get wrong is the second half of the sentence: it is nine to nine in the recipient’s local time, not the sender’s, and not the server’s.

For an Indian business dialling Indian numbers this distinction costs nothing, because both ends are in one zone. It starts mattering the moment anyone dials across zones, and the honest fix then is resolving the recipient’s zone from the numbering plan — not quietly widening the window because the edge case is inconvenient.

09:00 – 21:00

The TCCCPR window for commercial calls, in the recipient's local time

Source: TRAI, Telecom Commercial Communications Customer Preference Regulations

The check has to run immediately before the dial, not at queue time

This is the single most common way a compliant-looking system places non-compliant calls, and the failure is entirely undramatic.

A campaign of four thousand rows starts at 20:55. The platform checks the calling window once, at launch, and it passes — because at 20:55 it does pass. The dialler then works the list for the next two hours. Every row after 21:00 is a violation, and the system reports a completely successful campaign, because by its own accounting it checked and the check was fine.

The window has to be evaluated per call, at the moment of dialling. That is the only place where the answer is about the call being placed rather than about a campaign that was started.

Rule two: do-not-disturb is a registry lookup, and normalisation is most of the work

Subscribers can register preferences that block commercial calls, and calling a registered number is a regulatory event rather than a failed delivery. The lookup itself is straightforward. Making it work is a data problem, and it is the part that silently fails.

+91 98765 43210, 098765 43210 and 9876543210 are one number written three ways. A registry keyed on the raw string treats them as three different numbers, so a list that appears to be scrubbed blocks nothing at all — the uploaded number and the dialled number never reduce to the same key. Every number, on both sides, has to be normalised to one canonical form before anything is compared.

Both checks must fail closed, and that is a deliberate inversion

Most guards in a billing or telephony stack should fail open. If a balance reservation errors, refusing a funded customer’s call is worse than letting one uncosted call through — you can reconcile a rupee, you cannot un-refuse a customer.

Compliance runs the other way, and the asymmetry is worth stating plainly:

  • One call too many is a complaint to the regulator, against your sender identity, on the record.
  • One call too few is a retry.

So a do-not-disturb lookup that errors must refuse the call, not allow it. A platform that lets calls through when its compliance check is unavailable has chosen the expensive failure to avoid the cheap one.

A refusal is not an error, and it needs to be recorded as such

When a row is not called, somebody will eventually ask why. If the only answer lives in an application log, the answer in practice is “nobody knows”.

Each refusal should be stored against the row with a stable machine-readable reason — dnd_listed, outside_calling_hours — separate from whatever human sentence the interface shows this month. The sentence changes; the token is what you count, filter and produce when somebody asks how many calls were suppressed and on what grounds. That record is the difference between a compliance posture and a claim.

What to ask a vendor

Four questions, each with a wrong answer that sounds fine:

  • When do you check the calling window? “At campaign start” is the wrong answer.
  • What happens when the DND lookup fails? “We let the call through so the campaign is not held up” is the wrong answer.
  • How do you normalise numbers? If there is no answer, the scrubbing is decorative.
  • Can you show me why a specific row was never called? If that means reading logs, it will not survive an actual enquiry.

How Decibyl handles it

The calling window is evaluated immediately before each dial rather than once per campaign, against the organisation’s configured timezone. Numbers are normalised to a canonical form on both the uploaded list and the dial path, so the two reduce to the same key. Both checks fail closed: a lookup that errors refuses the call. Every refusal is stored against the row with a stable reason token, so the question “why was this number not called” has an answer that is not a log search.

We also publish what we are not: Decibyl holds no ISO 27001, SOC 2 or HIPAA certification, and says so on its security page. Data residency, consent handling and the DPDP position are set out on the DPDP page, and our lending and collections page leads with conduct expectations rather than efficiency, for the same reason this post leads with the window rather than the voice.

Compliance you can show someone, not claim.

Book a demo and we'll walk through the dialler's refusal record with you.