The model in one line
Vepler search is a two-step funnel. You type-ahead for free, and you pay only when a user picks a result and you fetch its full record.Discovery is free. Retrieval is charged once per address.
/v1/search/suggest as freely as your rate limits allow —
autocomplete on every keystroke costs nothing. The charge lands only on
/v1/search/retrieve, and the same address in the same
billing period is charged once, no matter how many times you fetch it.Quick start
Two calls: surface suggestions as the user types, then retrieve the one they choose.x-api-key header and run server-side — your API key
must never reach the browser. Put the search endpoints behind your own backend and proxy the
results to your UI.Step 1 — Suggest (free discovery)
uprn, and the
matched substrings for highlighting. They deliberately carry no coordinates, postcode, or
classification; those arrive in the retrieve step. This is what lets discovery stay free.
Parameters
address (individual properties) or location (postcodes,
towns, places). Omit to search both. Pair with source=address for the most predictable
proximity behaviour.residential, commercial, or all. Filters address results by property class.address (one row per property) or street (one row per named street / USRN — useful for
early keystrokes and street-level pickers).true, excludes historical and superseded addresses — only live, addressable records.lng.lat.geo_mode=restrict.bias (soft: near matches rank higher, distant matches
still returned) or restrict (hard: only address results within radius_meters are returned).
See Proximity.Response
The response is a standard list envelope. Address rows are the slim discovery projection:type is address, postcode, location, etc.; address rows carry uprn.null when no candidate set has formed yet.true when data already holds the complete match set — you can filter further keystrokes
locally instead of calling the API again.limit/offset).searchId, setComplete, hasMore,
totalCount, mainText, matchedSubstrings.Step 2 — Retrieve (charged selection)
uprn from the chosen
suggestion.
Parameters
uprn of the chosen suggestion. Its full record is returned and charged.search_id from the suggest response this selection came from. Supplying it completes
that search session and records the retrieval against it. Omit it (or pass an expired /
unknown one) and retrieve still works as a direct resolve, recorded as its own transaction.Response
| Status | Meaning |
|---|---|
200 | Full record returned (and charged, unless already claimed this period). |
400 | Invalid uprn or search_id. |
404 | UPRN not found — nothing is ledgered or charged. |
Getting autocomplete right
A search box that fires a raw request on every keystroke feels laggy and burns your rate limit. Four patterns make it feel instant. None of them are about cost — discovery is free — they are about latency and cleanliness.Debounce keystrokes (~300ms)
Set a minimum query length (3 chars)
Cancel superseded requests
AbortController to each request and abort the previous one when a new keystroke
fires. This prevents a slow early response from clobbering a fast later one (out-of-order
results).Flexibility — the tuning levers
Proximity: bias vs restrict
Pass the map centre (or the user’s location) aslat/lng to make results local. Two modes:
geo_mode=bias
geo_mode=restrict
radius_meters of the point are returned. Best
for “search within this area” experiences. Requires radius_meters.Source and classification
source=addressfor property-level typeahead;source=locationfor postcode / town pickers. Omit to blend both.classification=residential(default) /commercial/allto scope address results to the property class your product cares about.
Granularity: address vs street
granularity=street collapses results to one row per named street (USRN). It shines on early
keystrokes and in “pick a street” flows, where a list of every flat on the road is noise.
Candidate sets: narrow without re-fetching
When a query resolves to a small exact match set, the response carries asearch_id and, often,
set_complete: true. That is your signal to stop calling the API:
First real query returns a candidate set
search_id. If set_complete is true, data is the entire
match set.Further keystrokes narrow locally
set_complete is true, filter the rows you already hold client-side. No new request,
no latency, nothing to meter.Cost saving
Because discovery is free and retrieval is charge-once, keeping your bill low is mostly about not paying twice for the same address — the API already does most of this for you.Type freely — suggest is free
Retrieve only on selection
retrieve. Call it when a user actually picks a result — never speculatively
for every suggestion on screen.Charged once per address, per period
Cache within the period
Filter locally when set_complete
Link the session with search_id
search_id from suggest into retrieve so each charge is attributed to the search it came
from — cleaner reporting in your usage dashboard.Billing transparency headers
Every charged response tells you exactly what happened, so you can reconcile without guessing:| Header | Meaning |
|---|---|
X-Credits-Charged | Credits charged by this request (0 if already claimed this period). |
X-Already-Charged | true when this UPRN was already paid for this period — no new charge. |
X-Credits-Balance | Your remaining credit balance after the request. |
X-Search-Session request header (a UUID
you generate per end-user search) is available purely to group a user’s requests together in
your usage analytics — it does not affect billing. Billing deduplicates on the UPRN, on the
server.Rate limits
Suggest and retrieve are metered separately.Suggest throughput
429 with a Retry-After header. Debouncing keeps you well under it.Daily spend cap
429 handling and backoff, and contact us for higher limits.
FAQ
Do autocomplete keystrokes cost anything?
Do autocomplete keystrokes cost anything?
suggest is free — type-ahead on every keystroke does not run up a bill. You are charged
only when you retrieve the full record for a chosen address.If I retrieve the same address ten times this month, what am I charged?
If I retrieve the same address ten times this month, what am I charged?
X-Already-Charged: true) and cost nothing.Does a retry after a network timeout double-charge me?
Does a retry after a network timeout double-charge me?
Do I need to send search_id?
Do I need to send search_id?
Why don't suggestions include coordinates?
Why don't suggestions include coordinates?
retrieve step.
This split is what keeps autocomplete free.What's the difference between search_id and X-Search-Session?
What's the difference between search_id and X-Search-Session?
search_id is server-minted and links a suggest → retrieve flow for billing attribution.
X-Search-Session is a client-generated header purely for grouping requests in your own usage
analytics — it never affects what you are charged.Next steps
Address Billing & Sessions
Usage & Limits
429 handling, and backoff.API Reference
Authentication
x-api-key header.