Back to Insights
Technology

Knowing Who Is Calling Before They Say So

Caller recognition fails silently, because the number arriving in E.164 does not match the six ways a human typed it into your CRM. Number normalisation, the search rate limit nobody plans for, and the line between recognised and watched.

Published August 14, 2026
10 min read

The most valuable second of an automated phone call is the one before anybody speaks. In that second the number is already known, and if you can turn it into a name, an open order and a reason for calling, the entire conversation starts one step ahead. Almost every team underestimates how much work that second is, and almost all of the work is in the data rather than the code.

Why the first second is worth the effort

A caller who has to explain who they are, spell their name, and repeat their order number has already had a worse experience than the one they get from a competent human on the same line. Recognition is the difference between an agent that feels like a system and one that feels like the company.

It also shortens calls, and shorter calls matter directly on a per-minute platform. Thirty seconds of identification removed from every call is thirty seconds you do not pay for and the caller does not sit through. That arithmetic is why this is usually the first integration anybody asks for, ahead of the write-back that looks more impressive in a demo.

The number you get is not the number they stored

The telephone network hands us a number in E.164: a plus, a country code, and the national number with no punctuation. It is unambiguous and it is the same every time. Your CRM contains whatever a person typed while they were doing something else.

one-number-six-ways.txt
+31612345678      SIP INVITE, E.164, what we give you
 0612345678       typed by a colleague in a hurry
 06-12345678      typed by a colleague who likes dashes
 06 12 34 56 78   pasted from a signature block
 0031612345678    imported from an older system
 +31 6 12345678   copied from a website

 all six are one person
 an exact-match query finds one of them

An exact-match query on the incoming number finds the contacts stored in E.164 and misses everyone else. In a Dutch dataset that has been through an import or two, that can be most of the file, and the failure is silent: the lookup returns nothing, the agent politely asks who is calling, and nobody notices that recognition is quietly broken for half the customer base.

  1. 01

    Normalise on the way in

    Strip spaces, dashes and brackets, convert a leading 00 to a plus, and expand a national leading zero using the country you actually operate in. Do this in one function that both the lookup and any import path call, so the two can never drift.
  2. 02

    Search on the last significant digits

    The reliable key is the subscriber part without the country and trunk prefix, because that survives every formatting habit. Match on that, then verify the full number on the candidates you get back.
  3. 03

    Fix the source, once, in the background

    A normalisation pass over the existing contacts turns a permanent workaround into a one-off migration. It is unglamorous and it is usually the highest-value hour in the whole project.
What this costs when skipped

A recognition rate nobody is measuring

Recognition failure does not raise an error, so it never appears in a dashboard. The only way to know your real hit rate is to log every lookup with its outcome from the first day and look at the ratio. Teams that do this are routinely surprised in the wrong direction.

Search is capped far lower than you think

Having decided to search rather than to match exactly, you meet the second problem. Searching is a privileged operation in most CRMs and it is rationed separately from everything else.

HubSpot is the clearest example. A private app on Professional or Enterprise gets 190 requests per ten seconds, which is far more than any phone line will use. Search endpoints are not part of that allowance: they are limited to five requests per second per account, and that ceiling is shared with every other integration on the same account. Your marketing automation, your data warehouse sync and your voice agent all draw from the same five.

OperationWhat it costs you
Fetch a contact by its record IDOrdinary request, 190 per 10 seconds
Search a contact by phone numberSearch request, 5 per second for the whole account
Write a note to the timelineOrdinary request, and it can wait until after the call
Two of these look the same from the outside and are budgeted very differently.

Plan against your call volume plus everything else that already searches, not against your call volume alone.

Cache on the number, not on the contact

The way out is a cache, and the detail that matters is what you key it on. The instinct is to cache contacts. The correct key is the incoming number, including the numbers that resolved to nothing, because a repeat caller who is not in the CRM will otherwise cost you a search on every single attempt, and unknown callers ring back more often than known ones do.

A short lifetime is enough. Most of the value is in the same person calling twice in an afternoon, and a cache measured in hours keeps the search budget comfortable while staying fresh enough that a contact updated this morning is not wrong this afternoon. Pair it with an invalidation on the write path, so a call that creates or updates a contact drops that number from the cache on its way out.

One number, three people

Shared numbers are ordinary. A company switchboard, a household landline, a workshop phone that four engineers use. The lookup returns three contacts and the agent has to decide what to do with that, and the wrong choice is to pick the first one.

Greeting somebody by another person's name is worse than not greeting them at all. It is the one failure a caller repeats afterwards to a colleague. The safe behaviour is to use what the matches have in common and nothing else: the company, the open order, the account. Then let the caller supply the rest, which they will do in one sentence without noticing they were asked.

The rule

Confidence, not the top result

Return the match only when there is exactly one, or when the matches agree on the thing you were going to say. Anything else is treated as unknown. An agent that is right slightly less often and never confidently wrong is the one people trust.

The caller you cannot place

Some calls arrive with the number withheld, from a switchboard that presents a main line, or from somebody who has genuinely never called before. This is not an edge case to handle later. It is a large minority of inbound traffic, and the agent has to sound exactly as competent in that path as in the recognised one.

Which means the unrecognised greeting is written first and written properly, not derived by deleting the name from the other one. It also means the lookup failing and the caller being unknown must be different states internally, even if they sound alike to the caller, because one of them is a fault you want to see in your logs and the other is a Tuesday.

Knowing more than the caller expects

There is a line here worth walking deliberately. Looking up a caller by their number before they have identified themselves is legitimate and completely normal, and every contact centre has done it for decades. Reciting what you found is a different act.

A caller who hears good afternoon, Mrs de Vries feels recognised. The same caller who hears their address, their last invoice amount and their support history read back unprompted feels watched, and on a line where they have just been told they are speaking to an AI, that shift lands harder. Under the disclosure rules we covered in the piece on EU AI Act Article 50, the caller knows they are talking to a machine from the first sentence. What the machine volunteers immediately afterwards sets the tone for everything that follows.

The practical rule we apply is that the agent may use what it found to be helpful, and may confirm details the caller raises, but does not volunteer personal data the caller has not asked about. That is a prompt decision and an endpoint decision at the same time: the safest way to stop an agent reading out a field is not to send it the field, which is the same reasoning as returning an answer rather than a record.

What to build first

If you are starting this integration tomorrow, the order that saves the most time is counterintuitive. Write the normalisation function and run it over your existing contacts before you write a single line of agent code, because that step determines whether anything downstream works. Then build the lookup with the cache already in it, since retrofitting a cache means revisiting every decision about freshness. Then write the unknown-caller path. The recognised path is the easy one and it can come last.

The system-specific limits that shape all of this are on the integrations pages, and the general mechanics of making a request while somebody waits are in thirty seconds, one attempt.

Sources Rate limits are taken from HubSpot's usage guidelines and limits. The number formatting examples are the ones we see in Dutch contact data; E.164 is the format the SIP signalling delivers.