One-week geocoding pilot playbook: prove value before budget
Run a credible geocoding pilot in five working days using the free tier. Sample file, batch run, confidence review, API spike, decision memo.
Most geocoding evaluations fail before they produce a single useful number. The team spends two weeks fussing over API documentation, procurement opens a security review, someone suggests benchmarking six alternatives, and the original business problem — "can we geocode our customer database reliably enough to route field engineers?" — disappears into a backlog. Three months later the team is still on a spreadsheet.
The antidote is a constrained pilot with explicit exit criteria and a hard deadline. Five working days. One sample of your own data. Three acceptance criteria agreed on day one. A written decision memo by Friday afternoon. The whole thing runs on CSV2GEO's free tier — 3,000 calls per day, no credit card required — so procurement never enters the picture until you are already holding the answer.
This post is the playbook. It is written for the team lead who must prove value before asking for budget: the engineer who will run the integration spike, the analyst who will interpret the match-rate report, and the manager who will sign the decision memo. Each day has a concrete deliverable. Each deliverable builds directly on the one before it.
Before you start: agree the acceptance criteria
Do not begin the pilot without written agreement — even a Slack thread — on what "good enough" looks like. Three criteria cover almost every real evaluation.
Match rate on your own data. What percentage of your address rows return a geocode result above a meaningful confidence threshold? There is no universal target here; the right number depends entirely on your data quality and your use case. A logistics team routing expensive field-engineer visits tolerates far less ambiguity than a marketing team heat-mapping customer density. Write down your target before you see any results.
Precision on a hand-checked sample. Match rate tells you how many addresses resolved; it does not tell you whether they resolved to the right place. Plan to hand-check 30 to 50 results against a map on Wednesday morning. The confidence score points you to the rows most likely to be wrong — the hand-check confirms it.
Integration effort. How long does the REST integration spike take on day four? A geocoding API that needs a custom wrapper, a complex auth flow, and three support tickets to understand the rate-limit behaviour is a maintenance liability before a single address is processed.
Write these down. They are the decision criteria in Friday's memo.
---
How to work with the free tier
The free tier gives you 3,000 calls per day without a credit card. Sign up at csv2geo.com, retrieve your API key from /api-keys, and you are ready. There is nothing to approve.
One important detail about how calls are counted for the WEB batch tool: credits are consumed per address row, not per file. A file with 800 addresses costs 800 credits. With 3,000 per day, you can process a 2,500-row sample file comfortably within a single day's allowance, leaving 500 calls for ad-hoc spot checks and integration tests.
If your sample file is larger than 3,000 rows, trim it. The pilot does not need your whole database — it needs a representative sample. More on how to pick one below.
---
The five-day structure
Step 1 (Monday): Build your sample file and set success criteria
The sample file is the most important thing you do all week. A bad sample produces a result that does not generalise to production, and you will waste a week proving nothing.
How to pick a representative sample. Do not take the first 500 rows. Take a stratified sample: a slice from each data source, each region, each vintage. If your database has addresses entered by a call centre, addresses imported from a third-party list, and addresses typed by customers on a website, sample from all three. Those three sources will almost certainly behave differently, and the pilot should tell you that.
Aim for 500 to 2,500 rows. Small enough to process well within the daily free-tier limit; large enough to show meaningful variation. Strip any personally identifiable information beyond what the geocoder needs — in most cases that is a street address, city, and postcode. You do not need names, account numbers, or dates of birth in a geocoding test file.
The sample file format. The WEB batch tool accepts a simple CSV. One address per row. A header row with at least one column that the tool recognises as an address field. If your addresses are split across multiple columns (street, city, county, postcode), either concatenate them into a single address column before upload, or check the batch tool's column-mapping step — it will prompt you to map each column.
Document your success criteria today. Write down the three criteria from the pre-pilot section in a shared document. Include:
- The minimum match-rate percentage you consider acceptable (your number, based on your use case)
- The maximum tolerable error rate on the 30-50 row hand-check sample (e.g., "no more than 3 wrong out of 50")
- The maximum integration-spike time you consider acceptable (e.g., "if the REST spike takes more than half a day, we flag it as a risk")
Share the document with everyone who will sign the decision memo. Get explicit acknowledgement. This step takes twenty minutes and saves the Friday conversation from becoming a negotiation.
Monday deliverable: A clean sample CSV ready to upload, and a shared document with three written acceptance criteria.
---
Step 2 (Tuesday): Run the batch job and collect raw results
Upload your sample file through the WEB batch tool. The tool is at the same domain as your account — log in, find the batch section, upload the CSV, map your address columns, and submit.
While the job runs — typically a few minutes for a 2,000-row file — set up a simple tracking sheet. You want to capture, per row:
- The input address
- The returned latitude and longitude
- The confidence score (a decimal between 0 and 1)
- A flag column you will populate tomorrow during review
When the job completes, download the enriched CSV. It will include all your original columns plus the geocoding results appended. Do not start interpreting today — just make sure the file downloaded cleanly and that the column structure looks right.
Spot-check three to five rows manually. Take five addresses you personally know — your office, a customer site, a warehouse — and check that the returned coordinates are plausible. Drop the lat/lng into any mapping application and verify visually. This is not the formal hand-check; it is a sanity check that the integration is working before you invest Tuesday afternoon in analysis.
If the spot-check rows look wrong, stop and debug before proceeding. The most common causes: the address column was mapped incorrectly during upload, or the address strings contain encoding issues that silently corrupt the geocoder's input. Fix the input file and re-run.
Tuesday deliverable: A complete enriched CSV with confidence scores, confirmed to be structurally correct.
---
Step 3 (Wednesday): Review match rate and hand-check a precision sample
This is where you find out whether the tool works on your data. Do the analysis in two passes.
Pass one: match-rate analysis. In your spreadsheet tool of choice, compute a distribution of confidence scores across the full sample. A histogram with buckets at 0–0.4, 0.4–0.6, 0.6–0.8, 0.8–1.0 is sufficient. Note the percentage of rows in each bucket.
Rows above 0.8 are your high-confidence matches — the geocoder is sure. Rows between 0.6 and 0.8 are acceptable for many use cases but worth sampling in the hand-check. Rows below 0.6 are uncertain and warrant attention; below 0.4 is typically a failed or near-failed match. For a detailed explanation of how to interpret confidence scores as an acceptance metric, see Geocoding Confidence Scores Explained.
Calculate the proportion of rows above your agreed threshold. Compare it to your acceptance criterion. Write the number down — it goes in Friday's memo.
Pass two: precision hand-check. Select 30 to 50 rows for manual verification. Do not pick randomly: over-sample from the 0.6–0.8 confidence band, because that is where errors concentrate. Under-sample from the 0.8–1.0 band — those rows are almost always correct and hand-checking them wastes time.
For each row in the hand-check sample, compare the returned coordinates to a map. The question is binary: does this coordinate represent the correct address, or does it not? Record a yes/no in your flag column. Compute the error rate. Compare it to your acceptance criterion.
Segment the results. If your sample was stratified by data source, compute match rate and error rate per segment. This is where the pilot pays dividends beyond a simple pass/fail: you will almost certainly discover that one data source (say, the call-centre entries with inconsistent abbreviations) performs significantly worse than another (the structured imports). That is actionable information — it tells you which part of your pipeline needs address normalisation before geocoding, which changes the integration design on day four.
Wednesday deliverable: A written summary — two paragraphs, a table of match rates by confidence band, and a precision error rate from the hand-check. Circulate to the decision memo signatories.
---
Step 4 (Thursday): Run the REST integration spike
The WEB batch tool proves that the geocoder works on your data. The REST integration spike proves that you can build it into your system. These are different questions, and both matter.
Get your REST key. Your API key from /api-keys works for both the batch tool and the REST endpoints. No separate key, no separate approval step.
The simplest possible geocoding call. Start with a single address via curl to confirm auth is working:
curl -G "https://csv2geo.com/api/v1/geocode" \
--data-urlencode "q=10 Downing Street, London, SW1A 2AA" \
--data-urlencode "api_key=$CSV2GEO_API_KEY"The response looks like:
{
"results": [
{
"lat": 51.5034,
"lng": -0.1276,
"confidence": 0.95,
"formatted_address": "10 Downing Street, London SW1A 2AA, UK"
}
]
}Once that returns cleanly, build the minimal Python wrapper your team will actually use in production:
import os
import requests
API = "https://csv2geo.com/api/v1/geocode"
KEY = os.environ["CSV2GEO_API_KEY"]
def geocode(address: str) -> dict | None:
r = requests.get(
API,
params={"q": address, "api_key": KEY},
timeout=10,
)
r.raise_for_status()
results = r.json().get("results", [])
if not results:
return None
top = results[0]
return {
"lat": top["lat"],
"lng": top["lng"],
"confidence": top["confidence"],
"formatted": top.get("formatted_address"),
}Or in Node if that is your target runtime:
const API = 'https://csv2geo.com/api/v1/geocode';
const KEY = process.env.CSV2GEO_API_KEY;
async function geocode(address) {
const url = `${API}?q=${encodeURIComponent(address)}&api_key=${KEY}`;
const r = await fetch(url, { signal: AbortSignal.timeout(10_000) });
if (!r.ok) throw new Error(`http ${r.status}`);
const { results } = await r.json();
if (!results?.length) return null;
const { lat, lng, confidence, formatted_address: formatted } = results[0];
return { lat, lng, confidence, formatted };
}SDKs exist — Python and Node packages are available — but for an enterprise integration spike, the REST call is the right starting point. A few lines of requests or fetch have no version-pinning risk, no transitive dependency surprises, and are readable by any engineer who joins the team in eighteen months. If you decide later that a managed SDK saves meaningful time, you can add it; it is far easier to add a dependency than to remove one.
Time yourself. Note when you start the integration spike and when you have a working function that geocodes an address from your own application. That duration goes in the decision memo. If it took two hours, say two hours. If it took forty minutes, say forty minutes. The honest number is useful; a rounded-down estimate will embarrass you in the first production incident.
Test the confidence threshold in code. Add a branch that treats results below your agreed threshold differently — perhaps returning None and logging the address for manual review:
CONFIDENCE_THRESHOLD = 0.70 # your agreed criterion from Monday
def geocode_or_flag(address: str) -> tuple[dict | None, str]:
result = geocode(address)
if result is None:
return None, "no_result"
if result["confidence"] < CONFIDENCE_THRESHOLD:
return None, f"low_confidence:{result['confidence']:.2f}"
return result, "ok"This is the pattern you will actually ship. The pilot is the right moment to confirm it behaves correctly on your edge cases, not a week before go-live.
Thursday deliverable: A working geocoding function in your target language, confirmed against five to ten addresses from your sample file. A note on how long the spike took.
---
Step 5 (Friday): Write the decision memo
The decision memo is a one-page document with a recommendation. It is not a technical report. It is not a vendor comparison. It is the answer to the question the business is asking: "Should we proceed with this geocoding platform, and if so, on what terms?"
Template — copy and adapt this:
---
Geocoding Platform Pilot — Decision Memo *Date: [Friday's date]* *Author: [Your name]* *Audience: [Names of decision makers]*
Recommendation: [Proceed / Proceed with caveats / Do not proceed]
Pilot scope: We ran a [N]-row stratified sample of [describe your data sources briefly] through CSV2GEO's batch geocoding tool and REST API over five working days, using the free tier (3,000 calls/day, no contract required).
Match rate: [X]% of rows returned a result above our agreed confidence threshold of [Y]. Our acceptance criterion was [Z]%. [PASS / FAIL]
Precision on hand-check: We manually verified [N] rows selected from the 0.6–0.8 confidence band. [N] were correct, [N] were incorrect. Error rate: [X]%. Our acceptance criterion was [Z]% maximum. [PASS / FAIL]
Segment findings: [Note any significant variation between data sources — e.g., "Call-centre entries performed significantly below threshold and will require address normalisation before geocoding. Structured import rows performed above threshold."]
Integration effort: The REST integration spike from zero to a working geocoding function in [language] took [N hours / N minutes]. Our acceptance criterion was [Z]. [PASS / FAIL]
Cost projection:
- Production volume estimate: [N] addresses per month
- Paid tier starts at $54/month for 100,000 calls
- Full pricing: csv2geo.com/pricing/api
- Estimated monthly cost at production volume: $[X]
- First-year cost at production volume: $[X]
Risks and caveats:
- [e.g., "Call-centre address data requires normalisation. Estimated two-sprint effort before those rows perform acceptably."]
- [e.g., "Match rate on the [specific segment] was below threshold. Recommend a second sample focused on that segment before full rollout."]
Recommended next step: [e.g., "Proceed to procurement for a monthly paid tier. Begin address normalisation for call-centre data in parallel."]
---
This memo is deliberately short. A one-page document with a clear recommendation will be read and actioned. A twelve-page technical analysis will be deferred until next quarter.
Friday deliverable: The memo, shared with decision makers, with a meeting booked to discuss it if the recommendation is anything other than a clear proceed.
---
A note on cost projection
The memo template asks you to project monthly cost. Here is how to do that honestly.
Start with your production volume: how many address geocoding calls do you expect to make per month? Separate the one-time enrichment volume (your existing database) from the ongoing volume (new records per month).
CSV2GEO's paid tier starts at $54/month for 100,000 calls. The full pricing table is at csv2geo.com/pricing/api. Do not invent brackets — use the published numbers.
For an existing database enrichment, the cost is a one-time spend: divide your total address count by 100,000 and multiply by the per-100k rate. For ongoing production volume, the monthly cost is the relevant tier.
One refinement that often halves the projected cost: aggressive caching. An address that does not change should only be geocoded once. If your pipeline re-geocodes the same customer record every time it processes an order, you are spending many times more than you need to. See Caching Geocoding Results — 90% Cost Reduction for the pattern; implement a cache-key strategy before you finalise the cost projection, because it will materially change the number in the memo.
---
What the pilot cannot tell you
Honest scope. The one-week pilot answers three questions: match rate on your data, precision on a hand-checked sample, and integration effort. It does not answer everything.
Production latency under load. The free tier is not the right surface for load testing. If your use case involves synchronous geocoding in a user-facing request path — e.g., geocoding an address at checkout — you need a separate latency evaluation under realistic concurrency. The post P99 Latency — Why Averages Lie covers what to measure; run that evaluation after the pilot confirms match rate is acceptable.
Match rate on your full database. The pilot sample is a few thousand rows. Your production database might be five million. A 500-row sample will miss the long tail of unusual addresses — rural routes, non-standard formats, historical addresses from a legacy import. The pilot gives you a directional answer and tells you which segments to investigate further; it is not a guarantee about your full population.
Operational observability. How will you know when the geocoding pipeline is behaving badly in production? What metrics do you emit? What alerts fire when match rate drops? The pilot does not build any of that. See Observability for Geocoding Pipelines for the instrumentation plan to build before you go live.
---
Frequently Asked Questions
How many addresses do I need in the pilot sample to get a meaningful result? Five hundred rows is the practical minimum; 2,000 to 2,500 is better. Below 500 you will not see enough variation to trust the match-rate percentage. Above 3,000 you exceed the free tier's daily limit and have to either trim the sample or spread the run across two days. For most teams, 1,000 to 1,500 rows is the sweet spot — large enough to be directionally reliable, small enough to hand-check a meaningful slice on Wednesday morning.
Should I use the WEB batch tool or the REST API for the pilot run itself? The WEB batch tool for days two and three; the REST API for day four. The batch tool gives you a results CSV with confidence scores in minutes, no code required. The REST API spike on day four is a separate exercise — its purpose is to prove that your engineers can integrate the API, not to process the sample file faster.
What confidence score threshold should I use? That depends on your use case and your data. As a general orientation: above 0.8 is high confidence; 0.6 to 0.8 is usable for many applications but worth sampling in a hand-check; below 0.6 warrants caution. Do not use an industry benchmark as your threshold — measure it on your own data and calibrate it to your own tolerance for downstream errors. The post Geocoding Confidence Scores Explained covers the mechanics in detail.
What if my match rate is lower than my acceptance criterion? Do not reject the platform yet — investigate the low-confidence rows first. Low match rates almost always have a structural cause: inconsistent formatting in one data source, missing postcodes, truncated street names from a legacy import. Identify the cause, apply a normalisation step to the worst-performing segment, and re-run that segment. The pilot is the right moment to discover these issues, not six months into production.
What goes in the cost projection if I do not know my production volume yet? Use a range. Project for your best-case volume (minimum credible production use), your expected volume, and a 2× growth scenario. The memo is more useful with a range than with a false-precision single number. Pricing is published at csv2geo.com/pricing/api — use the current live brackets, not a number from a sales call.
Do I need to sign a contract before moving to the paid tier? No. The paid tier is self-serve — subscribe at csv2geo.com/pricing/api. There is no minimum commit on the entry tiers, no annual lock-in, and no procurement process beyond a credit card. If your organisation requires a purchase order for SaaS spend, that process runs in parallel with your technical evaluation — there is nothing to block on the vendor side while procurement does its work.
Is the free tier representative of what I will get on a paid plan? The API behaviour — response structure, confidence scoring, match logic — is identical across free and paid tiers. The only differences are the daily call limit and the absence of a credit card requirement. Your pilot results on the free tier are directly comparable to what you will see in production on a paid plan.
---
Related Articles
- Benchmarking Geocoding APIs — Honest Numbers — what to measure and what to ignore when comparing geocoding services
- Geocoding Confidence Scores Explained — how to interpret and threshold confidence scores as an acceptance metric
- Caching Geocoding Results — 90% Cost Reduction — the caching strategy that halves most teams' production cost projection
- Observability for Geocoding Pipelines — what to instrument before you go live, not after the first incident
- P99 Latency — Why Averages Lie — the latency evaluation to run after the pilot confirms match rate is acceptable
---
*I.A. / CSV2GEO Creator*
Use our batch geocoding tool to convert thousands of addresses to coordinates in minutes. Start with 100 free addresses.
Try Batch Geocoding Free →