- Multi-origin calls.
block_summary,block_pois,point_summary,point_pois, andpoi_catchmentnow accept many origins in one request: pass a list of GEOIDs (ordest_ids), or a list of(lat, lon)points, and the whole set is queried in a single call — one request against the 300/minute rate limit instead of one per origin. Results come back as a flat frame tagged by origin (geoid, ororigin_lat/origin_lon, ordest_id); per-originerrorsand anytruncatedorigins ride ondf.attrs. A batch is charged only for what the account can pay for, so a huge query stops at the balance rather than overspending.
Client.place_boundary(geoid)— the boundary polygon of a census place, as a one-row GeoDataFrame. Free (no API key); handy as aboundarylayer forclose_map.close_mapgains layered context and smarter defaults: it auto-zooms to the data, shows every attribute on hover, defaults to the ColorBrewerYlGnBuscale (blue = most accessible), and takes aboundaryoutline and semi-transparentbackgroundlayers (e.g. a city boundary, commute isochrones, or a walkshed under its POIs). Amarkargument drops an X on a point of interest (e.g. a starting point).
Client.place_pois(geoid, ...)— every point of interest within a census place (city or town), by place GEOID. The place analog ofpois_search; passtypeto get, e.g., all supermarkets in a city.close_map(gdf, ...)— a one-line interactive map (CARTO Positron basemap, hoverable points, or filled blocks that highlight the features meeting a criterion) for the GeoDataFrames the client returns. Built on plotly (theclosecity[maps]extra); GDAL-free.places()results now carry astatecolumn (two-letter USPS abbreviation), so same-named places are distinguishable.
Client()reads theCLOSECITY_KEYenvironment variable when noapi_keyis passed, so scripts and agents can authenticate without hardcoding the key. A 401 with no key set now carries an actionable hint pointing atCLOSECITY_KEYand the free-signup page (err.hint).- Ship the PEP 561
py.typedmarker so downstream type checkers (mypy, pyright) see the inline type hints. - Document that the client does not retry: on
RateLimitedError/ServiceUnavailableError, waiterr.retry_afterseconds and retry yourself.
Tabular results by default, across every route.
- New
outputmode replaces thespatialflag:Client(output = "spatial")(the default) returns aGeoDataFramewhere geometry applies and a plainpandas.DataFramefor catalog and summary routes;output = "tabular"returns a plainDataFrameeverywhere and never downloads block boundaries (the cheap path when you only want the numbers);output = "raw"returns the underlyingReply/Paginator. Set it on the client or per call. - Catalog routes (
modes(),destination_types(),vintage(),places()) and the block and point summaries now return data frames instead of nested replies.block_summary()/point_summary()broadcast the origin GEOID to ageoidcolumn.isochrone(format = "blocks")now converts too. - Metering and envelope metadata (
tokens_charged,tokens_remaining,etag,block_geoid,assumptions, ...) ride ondf.attrs. - New
to_pandas()module function andReply.to_pandas()/Paginator.to_pandas()methods, beside the existing geopandas ones.pandasis now a direct dependency.
First public release of the closecity Python client for the Close API
(api.close.city).
- A typed
Clientover the metered, read-only public endpoints: catalog, place lookup, block and point summaries and POIs, POI search, detail, and catchment, areal block queries, and isochrones. - Feature methods return
geopandas.GeoDataFrameobjects by default. Passspatial=Falsefor the rawReply/Paginator. Block boundaries are joined withpygris(thetigerextra). - First-class metering (
tokens_charged,tokens_remaining), ETag/304 conditional requests, keyset pagination (Paginator), and typed RFC 9457 errors. places()looks up a city or town by name and returns its GEOID and centre.