Quickstart
There's no hosted service to sign up for. You run the API and CLI yourself from the repo.
1. Install the CLI
The only real client today is a Python command-line tool — not a Python SDK object, not JS/Ruby/Go packages.
pip install fastopendata-client # installs the `fastopendata` command
2. Authenticate
The API uses short-lived JWTs (OAuth2 password flow), not API keys. There's no dashboard to generate one from — you authenticate against your own running server with a username/password created via /signup.
fastopendata login # prompts for username / password, writes a token to # ./.fastopendata_token — re-authenticates automatically when it expires
3. Make your first call
Pass a structured or free-form address. The server geocodes it via a self-hosted Nominatim instance and returns the raw match.
fastopendata geocode --street-number "350 5th Ave" --city "New York" --state "NY" # → Response from FastOpenData: {'place_id': ..., 'lat': 40.7484, 'lon': -73.9857, ...}
POST /structured_geocode
Geocode a single structured address. This is the real, working endpoint today — it proxies the request to a self-hosted Nominatim instance and returns Nominatim's own response shape.
Body parameters
| Name | Type | Description |
|---|---|---|
| street | string | Street address. |
| city | string | City name. |
| county | string | County name. |
| state | string | State name or abbreviation. |
| postalcode | string | ZIP code. |
| country | string | Country name. |
All fields are optional individually, but you need enough of them for Nominatim to find a match. Requires a bearer token from /token.
GET /health
Unauthenticated liveness check.
Returns {"status": "ok"}.
Response shape
The response is a direct pass-through of a single Nominatim search result — there's no custom envelope, no _meta block, and no enrichment fields yet.
{
"place_id": 127365481,
"licence": "Data © OpenStreetMap contributors, ODbL 1.0",
"osm_type": "way",
"osm_id": 98765432,
"boundingbox": [40.7481, 40.7487, -73.9860, -73.9854],
"lat": 40.7484,
"lon": -73.9857,
"display_name": "350, 5th Avenue, Manhattan, New York, NY 10118",
"place_rank": 30,
"category": "building",
"type": "yes",
"importance": 0.71
}
Error behavior
There's no structured error-code system yet — just standard HTTP status codes from FastAPI.
| Status | Meaning |
|---|---|
| 401 | Missing, invalid, or expired bearer token. |
| 404 | Nominatim found no match for the address. |
| 500 | Nominatim itself returned an error. |
There is currently no rate limiting, no 429 handling, and no partial-failure / 503 behavior for upstream sources — because there's only one upstream source (Nominatim) and no quota system.
Planned, not built
These are real goals for the project, listed here instead of documented as if they exist:
/free_form_geocodeexists as a route but is currently a stub that returns nothing.- A batch endpoint for looking up many addresses in one request.
- A
/fieldsendpoint describing an actual schema, once one exists. - Enrichment fields (Census ACS, TIGER geography, OSM points of interest, and more) joined onto the geocoding response — the ETL code for ingesting these datasets already exists in the repo, it just isn't wired into this API yet.
- Rate limiting and a real API-key system, once there's a reason to need one.
Methodology
Geocoding today runs entirely through a self-hosted Nominatim instance (OpenStreetMap data, ODbL 1.0 license) — there is no Census Bureau Geocoder integration, and no Google or other proprietary geocoding service involved.
Separately, the repository contains real ETL pipelines (Snakemake-based) for ingesting Census ACS/PUMS, TIGER/Line, SIPP, AHS, OpenStreetMap, Wikidata, and Foursquare Places data — built for a graph-processing project, not yet connected to this address API. See packages/fastopendata/config.toml in the repo for the exact dataset list and sources.
Source attribution
Geocoding data is © OpenStreetMap contributors, licensed ODbL 1.0, served via Nominatim per its usage policy. All planned Census Bureau data is public domain.