Matching geocoding APIs to use cases: a decision guide

56 endpoints, 9 API surfaces, one practical guide. Match your use-case to the right CSV2GEO endpoint family before writing production code.

| August 02, 2026
Matching geocoding APIs to use cases: a decision guide

Ninety percent of geocoding integration mistakes are not bugs. They are surface-selection errors — teams that reach for the forward-geocoding endpoint when the data they already have are coordinates, or who call a per-address REST endpoint in a loop when the batch file tool would cost one-tenth as much and finish in a fraction of the time. These are not obvious mistakes. The API accepts the request either way; it just bills you for a worse architecture.

CSV2GEO exposes 56 endpoints across nine distinct surfaces. Each surface is designed for a specific shape of problem. This post maps every common use-case pattern to the right surface, gives you the shortest working code path to get started, and calls out the failure modes that bite teams who pick incorrectly. Read it once before you write your integration; refer back to it when you are evaluating a new feature request that touches location data.

The surfaces covered: web batch file upload, forward geocoding, reverse geocoding, boundaries and administrative divisions, routing (route, matrix, isoline, optimisation), elevation, static maps, aerial imagery, and distance and reachability analysis. By the end you will have a decision tree you can hand to any engineer on your team.

---

The core question: what shape is your problem?

Before choosing an endpoint, answer four questions.

1. Do you have addresses or coordinates? Addresses go to forward geocoding or batch upload. Coordinates go to reverse geocoding, elevation, aerial imagery, or any surface that takes lat,lng directly.

2. Are you doing this once, in bulk, or continuously? One-off bulk file enrichment belongs to the web batch tool. Continuous intake from an application belongs to the per-key REST endpoints. Mixing these up is the most expensive surface-selection error in the stack.

3. Is a human waiting for the answer, or is it a background job? Synchronous REST calls are fine when a user is waiting for a page to render and the round-trip is one call. Batch jobs with millions of rows are not a good fit for synchronous per-row REST calls regardless of what the rate limit allows.

4. What is the answer shape you need — a point, a boundary, a distance, an image, or a number? Each answer shape maps cleanly to exactly one surface. If you catch yourself post-processing a geocoding response to derive a boundary or a reachability estimate, you have picked the wrong surface.

With those four questions answered, the decision tree is almost mechanical. Here is the surface-by-surface mapping.

---

Surface 1: Web batch tool — one-off file enrichment

When to use it. You have a spreadsheet or CSV of addresses and you need to enrich them once. The output is a downloaded file. There is no application code, no API key management, no retry logic — you upload the file, the job runs, you download the result.

When NOT to use it. Anything recurring. Anything triggered by user action. Anything where you need the result in your application's data store within a few seconds. Those shapes all belong to REST.

Cost model. Credits are charged per address row, not per file. A file with 10,000 address rows costs 10,000 credits. The free tier covers 3,000 calls per day, which is 3,000 rows if you are running the batch tool interactively and your file does not exceed that count.

Failure mode. Teams sometimes upload the same file every day as a proxy for a proper integration because they haven't yet built the REST pipeline. This creates a manual dependency in the data workflow, usually owned by one analyst who leaves at some point. If you are running the same file enrichment more than twice, automate it.

---

Surface 2: Forward geocoding — addresses to coordinates

When to use it. Your application receives a free-text address — from a form, from an imported CSV, from a CRM — and you need to resolve it to a lat/lng with a confidence score. This is the most commonly understood surface and the one most teams default to even when it is the wrong choice.

Endpoint: GET /api/v1/geocode

A minimal curl:

curl -s "https://csv2geo.com/api/v1/geocode" \
  --data-urlencode "q=1600 Pennsylvania Ave NW, Washington DC" \
  --data-urlencode "api_key=$CSV2GEO_KEY" \
  -G | jq '.results[0] | {lat, lng, confidence}'

Python equivalent:

import os, requests

def geocode(address: str) -> dict:
    r = requests.get(
        "https://csv2geo.com/api/v1/geocode",
        params={"q": address, "api_key": os.environ["CSV2GEO_KEY"]},
        timeout=10,
    )
    r.raise_for_status()
    results = r.json().get("results", [])
    return results[0] if results else None

Node:

const API = 'https://csv2geo.com/api/v1/geocode';
const KEY = process.env.CSV2GEO_KEY;

async function geocode(address) {
  const url = `${API}?q=${encodeURIComponent(address)}&api_key=${KEY}`;
  const r = await fetch(url);
  if (!r.ok) throw new Error(`http ${r.status}`);
  const { results } = await r.json();
  return results?.[0] ?? null;
}

Confidence scores matter. A response with confidence: 0.4 is the API telling you it made a guess. Treat anything below 0.7 as needing manual review or a fallback. See Geocoding confidence scores explained for the full treatment.

When NOT to use forward geocoding. If your data already has lat/lng columns, you do not need this endpoint — go to reverse geocoding or straight to whichever point-input surface you need. Calling forward geocoding on addresses just to get back to a lat/lng that is already in your database is a common, expensive mistake.

Data scale. The forward geocoding index covers 504M+ addresses across 63 countries. If your addresses are in an unusual territory, test coverage in the free tier before committing the integration.

---

Surface 3: Reverse geocoding — coordinates to addresses

When to use it. You have lat/lng — from a GPS device, a user's browser, a telemetry stream, a delivery driver's handset — and you need to resolve it back to a human-readable address or a structured administrative record.

Endpoint: GET /api/v1/reverse

curl -s "https://csv2geo.com/api/v1/reverse" \
  --data-urlencode "lat=51.5074" \
  --data-urlencode "lng=-0.1278" \
  --data-urlencode "api_key=$CSV2GEO_KEY" \
  -G | jq '.results[0] | {street, city, country, confidence}'

Failure mode. Teams use reverse geocoding for everything coordinates-related, including things that belong elsewhere. Reverse geocoding tells you what address is at a point. It does not tell you which administrative division that point falls within (boundaries surface), it does not tell you the elevation (elevation surface), and it does not tell you what is reachable from that point (routing surface). If you are post-processing a reverse geocoding response to extract a county name or derive a flood risk, you are on the wrong surface.

Accuracy and the distance question. Reverse geocoding accuracy varies by address density. Urban centres resolve to the nearest street number. Rural areas may snap to a road segment or a settlement centroid. The practical question is: how far is the returned address from the input coordinate? Shipping that distance to the user (or logging it for monitoring) is a sign of a mature integration. See Reverse geocoding accuracy in meters for the measurement methodology.

---

Surface 4: Boundaries and administrative divisions — "what area is this in?"

When to use it. You have a coordinate and you need to know which named administrative area it falls within — country, region, state, county, municipality, postcode zone. The canonical example is a SaaS product that needs to assign a user's location to a sales territory, a tax jurisdiction, or a reporting region.

Endpoint family: /api/v1/divisions (or equivalent boundaries endpoints in the 56-endpoint surface)

Why this is different from reverse geocoding. Reverse geocoding answers "what is the address here?" Boundaries answers "what areas contain this point?" The two can return consistent administrative fields, but boundaries endpoints are optimised for hierarchical containment queries — they can tell you every administrative level from country down to postcode in a single response, and they are the right surface when your primary use case is the classification, not the street address.

Typical use cases: tax jurisdiction assignment, sales territory routing, compliance classification (is this address in a restricted region?), electoral analytics, delivery-zone assignment.

Failure mode. Using forward geocoding to derive a county name by parsing the structured address response. That works at low scale and breaks at high scale because structured address fields are not always populated with the granularity you need, and the response format differs by country. Use the boundaries surface directly.

---

Surface 5: Routing — route, matrix, isoline, and optimisation

When to use it. Your problem involves movement. Not just "where is this?" but "how do I get there?" or "what can I reach from here?" or "in what order should I visit these ten stops?"

The routing surface is actually four related surfaces; pick the right one.

Route (`/api/v1/route`) — point A to point B, with a path, turn-by-turn instructions, and a duration. Use this when a user needs to know the route between two specific places.

Matrix (`/api/v1/matrix`) — N origins × M destinations in one call, returning travel times and distances for every pair. Use this for nearest-facility assignment (which of my 20 warehouses is closest to this postcode?) or for building a cost matrix for optimisation. Do not make N×M separate route calls — that is the single most common routing surface error.

Isoline (`/api/v1/isoline`) — a polygon that represents all points reachable within a given time or distance from an origin. Use this for service area analysis, coverage modelling, or "show me all addresses within 30 minutes' drive."

Optimise (`/api/v1/optimize`) — given a set of stops, find the order that minimises total travel time or distance. Use this for delivery sequencing, field-service routing, and any "travelling salesman"-shaped problem with up to a few hundred stops. See Dispatch console: 5,000 stops per day for a production-grade worked example.

Failure mode on matrix. Teams call the route endpoint in a loop with asyncio.gather or Promise.all to simulate a matrix. This works until concurrency limits bite, and it pays the per-call overhead for every pair instead of one call. Use the matrix endpoint from the start.

A minimal matrix call in Python:

import os, requests

def travel_time_matrix(origins, destinations):
    """
    origins, destinations: lists of {"lat": ..., "lng": ...}
    Returns a 2-D list: matrix[i][j] = travel time in seconds from origins[i] to destinations[j].
    """
    r = requests.post(
        "https://csv2geo.com/api/v1/matrix",
        json={
            "origins": origins,
            "destinations": destinations,
        },
        params={"api_key": os.environ["CSV2GEO_KEY"]},
        timeout=30,
    )
    r.raise_for_status()
    return r.json()["durations"]

---

Surface 6: Elevation — terrain as a number

When to use it. You need the height above (or below) sea level of one or more points. Flood risk signal, view potential, slope analysis, route-elevation profiles, altitude-dependent pricing.

Endpoint: GET /api/v1/elevation

Accepts up to 500 points per request. Returns metres above sea level, preserving input order. Negative values are real — the Dead Sea shore returns −415 m, Death Valley's Badwater Basin returns −80 m. If your current provider returns 0 for those points, that is a clamped-to-zero fallback masquerading as a real DEM.

curl -s "https://csv2geo.com/api/v1/elevation" \
  --data-urlencode "points=27.9881,86.9250|36.4615,117.1100" \
  --data-urlencode "api_key=$CSV2GEO_KEY" \
  -G | jq '.results[] | {lat, lng, elevation_m}'

Anchor probes for sanity-checking integration: Mt Everest → 8,731 m, Mauna Kea → 4,198 m, Denver → 1,597 m, Paris → 46 m, Miami → 1 m.

Failure mode. Calling /api/v1/elevation one point at a time inside a loop when you have a batch of addresses. The endpoint accepts 500 points per call — use it. See Enriching property data with elevation API for the full batch pipeline pattern.

When NOT to use elevation. Elevation is terrain height, not building height. A 30-storey tower and a single-storey bungalow at the same coordinate return the same elevation. If you need roof height, you need the aerial imagery surface.

---

Surface 7: Static maps — visual output without a rendering stack

When to use it. You need a map image — for a PDF report, an email notification, a print layout, a dashboard screenshot, a mobile app thumbnail — and you do not want to run a tile-rendering stack or pay for a full dynamic mapping library.

Endpoint: GET /api/v1/staticmap

Parameters control centre point, zoom, size, and optional markers or polylines. The response is a raw PNG (or JPEG), suitable for <img src>, S3 upload, or direct embedding in a PDF.

curl -s -o "map.png" \
  "https://csv2geo.com/api/v1/staticmap?lat=51.5074&lng=-0.1278&zoom=14&size=600x400&api_key=$CSV2GEO_KEY"

When NOT to use static maps. When users need to pan, zoom, or interact with the map. Static maps are a rendering shortcut for fixed-view output; they are not a substitute for a dynamic mapping library in an interactive UI.

Failure mode. Generating a new static map on every page load for the same location. These are cacheable. Cache aggressively at the CDN or application layer — a map of a fixed address at a fixed zoom does not change. See Caching geocoding results — 90% cost reduction; the same cache strategy applies verbatim.

---

Surface 8: Aerial imagery — US property visuals

When to use it. You need a top-down aerial photograph of a specific parcel. Insurance underwriting, property listing enrichment, construction permit review, field-service pre-visit intelligence.

Endpoint: GET /api/v1/property/image

Coverage: contiguous United States plus Alaska, Hawaii, and Puerto Rico. Outside that footprint the endpoint returns HTTP 400. Build the fallback path before you ship; plan for a small out-of-coverage rate even within the US for edge regions.

curl -s -o "parcel.jpg" \
  "https://csv2geo.com/api/v1/property/image?lat=34.0522&lng=-118.2437&size=350&format=jpg&api_key=$CSV2GEO_KEY"

The imagery is sourced from a public-domain US federal aerial programme flown on a multi-year cycle. Image cache is 30 days server-side — repeat lookups against the same coordinate within that window do not incur additional credits.

When NOT to use aerial imagery. If you need change detection between two recent dates, centimetre-scale resolution for structural engineering, or coverage outside the United States. Public aerial programme imagery has a two-to-three year refresh cycle per state; it is not suitable for detecting month-to-month changes. For those use cases you need a commercial satellite contract with on-demand tasking.

Failure mode. Not building the out_of_coverage fallback and silently dropping non-US or edge-region records. This creates a reconciliation problem that surfaces weeks later. Always handle the 400 explicitly.

---

Surface 9: Distance and reachability analysis — "how far / what's reachable?"

This surface overlaps with routing but deserves its own framing because the question shape is different. Routing answers "how do I get from A to B?" Reachability analysis answers "given an origin, what set of destinations can I reach within some constraint?"

The two tools here are the matrix (which gives you a travel-time or distance number for every origin-destination pair) and the isoline (which gives you the geographic boundary of reachability from an origin).

Matrix for assignment problems. "Assign each of 50,000 customer postcodes to the nearest one of 200 service centres" is a matrix problem. One API call with 50,000 origins and 200 destinations returns the full table. Do not simulate this with loops.

Isoline for coverage problems. "Draw the area reachable within 45 minutes of this logistics depot" is an isoline problem. The returned polygon is a GeoJSON geometry you can render on a map, run a point-in-polygon test against, or pass directly into a spatial database query.

import os, requests

def isoline(lat: float, lng: float, minutes: int) -> dict:
    r = requests.get(
        "https://csv2geo.com/api/v1/isoline",
        params={
            "lat": lat,
            "lng": lng,
            "contours_time": minutes,
            "api_key": os.environ["CSV2GEO_KEY"],
        },
        timeout=30,
    )
    r.raise_for_status()
    return r.json()["features"][0]["geometry"]  # GeoJSON polygon

---

HowTo: apply the decision guide to a real integration

Step 1: Write down the data shape you have on entry

Before you open the API docs, write one sentence: "I have [X] and I need [Y]." If X contains free-text addresses and Y contains lat/lng, you are forward geocoding. If X contains lat/lng and Y contains addresses or administrative classifications, you are reversing or querying boundaries. If X contains addresses and Y contains a downloaded enriched file, you are using the batch tool. If X contains lat/lng and Y contains a terrain height, you are calling elevation. If X contains a set of stops and Y contains the optimal visit order, you are on the optimise endpoint.

Step 2: Check whether you need batch or streaming

If the records arrive all at once (a CSV upload, a nightly ETL job, a one-time import), use the batch tool or call REST in batches of 500. If records arrive continuously and a user or downstream system is waiting for the result within a few seconds, use the per-request REST pattern with a per-user API key from /api-keys.

Step 3: Validate coverage before committing to the integration

Not every surface covers every country. Forward geocoding: 63 countries, 504M+ addresses. Elevation: global. Aerial imagery: US only (contiguous + AK + HI + PR). Routing: check the coverage page for your specific geography — coverage for routing is narrower than for geocoding. Test a representative sample of your data in the free tier before building the integration.

Step 4: Instrument the surface selection in your observability stack

Every endpoint call in your application should log the surface name alongside the standard HTTP metrics. If you discover three months into production that you are spending 70% of your API budget on forward geocoding calls that return coordinates you immediately throw away (because the downstream call is elevation-only), your logs will show you that pattern. Surface-level spend attribution is worth the twenty minutes to instrument. See Observability for geocoding pipelines for the full instrumentation pattern.

Step 5: Apply the cache rule per surface

Caching behaviour differs by surface, but the rule is simple: anything that takes a fixed input and returns a fixed output with no time dependency can be cached aggressively. Forward geocoding: addresses do not move — cache with a long TTL. Reverse geocoding: same. Elevation: terrain moves on geological timescales — cache indefinitely. Aerial imagery: 30-day server-side cache, mirror it in your CDN. Static maps: fixed zoom and centre means the image is static — cache at the CDN edge. Routing: time-sensitive (road closures, traffic) — cache with a short TTL or no cache if real-time accuracy matters.

---

The quick decision table

| Your question | Your input | Surface to use | |---|---|---| | What are the coordinates for this address? | Free-text address | Forward geocoding | | What address is at these coordinates? | lat, lng | Reverse geocoding | | Enrich a CSV file, one-off | Address column in a file | Web batch tool | | What administrative area is this in? | lat, lng | Boundaries / divisions | | How do I get from A to B? | Two coordinates | Route | | How long between every pair of N locations? | N×M coordinates | Matrix | | What area can I reach in 30 min? | Origin + time budget | Isoline | | Optimal order for 20 stops? | Set of coordinates | Optimise | | What is the terrain height here? | lat, lng | Elevation | | Give me an aerial photo of this parcel | lat, lng or address | Aerial imagery (US only) | | Generate a map image for a PDF | Centre lat, lng, zoom | Static map |

---

Cost and tier considerations

The free tier gives you 3,000 calls per day — enough to test every surface listed above on a representative sample before spending a pound. Paid tiers start at $54/month for 100,000 calls. A call is one credit: one forward geocode, one reverse geocode, one elevation point (or one batch call that includes up to 500 points), one aerial image, one matrix call. See csv2geo.com/pricing/api for the current tier brackets.

The biggest lever on cost is surface selection. Teams that pick the right surface typically spend 30-60% less than teams that simulate it with a combination of the wrong endpoints plus post-processing. The matrix example above is illustrative: N×M separate route calls versus one matrix call is not just more credits — it is more latency, more retry surface, more error-handling code.

---

Frequently Asked Questions

Which surface is most commonly misused? Forward geocoding. Teams reach for it reflexively when their data already has lat/lng columns — coordinates that should go directly to reverse geocoding, elevation, or aerial imagery. Every forward-geocoding call on data that already has coordinates is a wasted credit and an unnecessary network round-trip.

Can I use a single API key across all surfaces? Yes. One key from /api-keys authenticates calls to every surface. Credit billing is unified — you are not managing separate buckets per surface. The free tier's 3,000 calls/day applies across all surfaces combined.

Should I use the web batch tool or REST for a 1M-row import? REST, with batching. The web batch tool is designed for files you upload manually through a browser; it is not built for programmatic 1M-row imports. Use REST in batches of 500 rows per call, with a worker queue and exponential backoff on errors. See Exponential backoff — when to retry, when to stop for the retry pattern.

What is the right surface for "show me coffee shops within 500 m of this address"? That is the Places/nearby surface, which is part of the 56-endpoint set but outside the nine surfaces focused on in this post. It is a proximity search: you pass a coordinate and a radius, and you get back a list of POIs. The elevation surface integrates with it via ?include=elevation on the response.

Is aerial imagery available outside the US? No. The aerial imagery endpoint is US-only (contiguous United States plus Alaska, Hawaii, and Puerto Rico). Outside that footprint the endpoint returns HTTP 400. There is no equivalent surface with global coverage at equivalent resolution from a public-domain source.

How do I know if my integration is using the right surface? Log the endpoint name on every call and aggregate spend by endpoint over a rolling 7-day window. If you see disproportionate spend on one endpoint — especially forward geocoding — audit the callers. More often than not you will find one code path that is calling it unnecessarily when the data already has coordinates.

Do SDKs expose all 56 endpoints? SDK coverage varies by language and version. The REST API is the authoritative interface and is always complete. We recommend wrapping the REST calls in a thin internal client rather than depending on an SDK version for enterprise production pipelines — it eliminates the upgrade treadmill and gives your team full control over retry and error-handling behaviour.

---

Related Articles

---

*I.A. / CSV2GEO Creator*

Ready to geocode your addresses?

Use our batch geocoding tool to convert thousands of addresses to coordinates in minutes. Start with 100 free addresses.

Try Batch Geocoding Free →