Articles routing

What a serviceability API should return, and what it should refuse to

Whether you serve an address is a yes, a no, or an admission of uncertainty. An API that only has the first two is one that guesses.

A serviceability check is one of the simplest questions a business system asks: can we do this, here. It is also one of the easiest to design badly, because the obvious interface is a boolean and the honest answer is not always one.

Three answers, not two

Yes, and here is who. The address resolved, a territory covers it, an owner can do the work. The owner belongs in the response: a caller who has to make a second request to find out who is going to do the job will cache the first one and get it wrong.

No, and here is why. Not one no. “Outside every territory” and “inside a territory whose owner does not do this work” and “inside a territory that is closed today” are three different situations, and the front end shows a different thing for each. Collapsing them into false means the customer gets the same unhelpful sentence whichever one applies.

We do not know. The address could not be located, or was located too imprecisely to decide. This is the answer most APIs do not have, and its absence is why they produce confident wrong answers.

Why uncertainty has to be first class

A geocoder can always return something. Given a street it does not recognise it will hand back the middle of the postal area, and that point sits in a territory just as convincingly as a rooftop does.

If the response cannot distinguish those, then somewhere in your product a customer is being told they are covered based on a point a quarter of a mile from their house. The failure is silent by construction: it looks identical to success.

So precision is part of the answer, and the caller decides what to do with it. For a marketing page, a postal-area match is fine. For dispatching a van, it is not. Same API, different thresholds, both able to be right. See geocoding precision for what those levels mean.

What belongs in the response

A stable reason code. A string a caller can branch on, that does not change when the wording does. Front ends will render your prose if you make them, and then a copy edit becomes a breaking change.

Who, when the answer is yes. An opaque id and a display name.

How the address was located. Precision, and what the geocoder matched.

The version that decided. The single field that makes support possible. Six weeks later, “which map answered this” is the difference between an explanation and a shrug.

Optionally, the trace. Which territories contained the point, which rules ran, which one decided. Expensive to return on every call and worth having behind a flag, because it turns a support ticket into a two-minute read.

What does not belong

A confidence percentage. It reads as precise and it is invented. Report what you actually know, which is what the geocoder matched.

Free text meant for a customer. The API does not know whether it is being called from a booking form, a call script or a batch job, and the right sentence is different in each.

A guess. If the address cannot be located, saying so is the whole value.

Two properties that matter more than they sound

The same inputs give the same answer. Same address, same version, same result, every time. Routing that varies between calls cannot be tested, cannot be supported, and cannot be explained to somebody who got a different answer this morning.

A refusal is cheap and countable. Every no is a fact about demand you do not serve. Aggregated, the refusals are the most valuable output the system has, and they only exist if the API is willing to produce them rather than assign everything to somebody.

The check belongs in front of the form

The most common place to put a serviceability check is after a lead has been captured, as a validation step. That is the wrong end. A visitor who fills in a form you are going to reject has spent their time and yours, and they get an email that reads as a rejection.

Ask first, and the ones you cannot serve leave in ten seconds knowing where they stand, while the ones you can serve arrive at the form already knowing you cover them. The refusals still get counted.