I made a free REST API that turns 'find cafes in Paris' into structured JSON

typescript dev.to

Every few months I need local business data -- restaurants near an office, gyms in a neighborhood, dentists in a city. The usual path: learn the Overpass query language, handle raw OSM tags, geocode addresses separately, parse nested JSON.

I wanted something simpler: pass a city and category, get clean JSON back. So I built BizData API.

Quick start

curl "https://bizdata-web.vercel.app/api/businesses?location=Paris&category=cafe&limit=2"
Enter fullscreen mode Exit fullscreen mode
{"total":2338,"location_resolved":"Paris, France","businesses":[{"name":"Cafe Exemple","category":"cafe","address":"Avenue Parmentier, 28","phone":"+33 1 48 05 94 36","website":"https://aunreve.fr","email":"contact@aunreve.fr","lat":48.8606,"lon":2.3787,"opening_hours":"We-Sa 08:30-19:00; Su 09:00-19:00"}]}
Enter fullscreen mode Exit fullscreen mode

No API key. No signup. One URL.

What it does that raw Overpass doesn't

Overpass is powerful but requires learning a custom query language:

[out:json][timeout:30];
node["amenity"="cafe"](around:5000,48.8566,2.3522);
out center tags;
Enter fullscreen mode Exit fullscreen mode

BizData handles the geocoding, query building, tag mapping (37 normalized categories), and result formatting. You get a standard REST endpoint with clean JSON instead of a custom QL.

Three endpoints

GET /api/businesses -- Find businesses by location and category.

Param Required Description
location Yes City or address
category Yes One of 37 types
radius_km No Search radius, default 5
limit No Max results, default 50, max 500

GET /api/count -- Count businesses across categories. "How many restaurants, cafes, and bars in London?" returns 6,763.

GET /api/categories -- List all 37 available categories.

Error handling

Bad category:

{"error":"Unknown category: pizza. Available: accountant, bakery, bank, ..."}
Enter fullscreen mode Exit fullscreen mode

Missing params:

{"error":"Missing required parameter: location"}
Enter fullscreen mode Exit fullscreen mode

Performance

  • /api/categories: ~50ms (cached)
  • /api/businesses (50 results): 1-3 seconds
  • /api/count (all categories): 10-30 seconds
  • Results cached for 1 hour on Vercel's edge

Limitations

  • Data quality depends on OpenStreetMap contributors
  • Coverage: excellent in Europe, solid in major US/Asian cities, sparse in rural areas
  • Shared Overpass API pool
  • Some businesses lack phone/email/hours

Built with

TypeScript, Vercel serverless functions, OpenStreetMap Nominatim (geocoding) + Overpass API (data).

Try it

Interactive demo: bizdata-web.vercel.app

All 37 categories: accountant, bakery, bank, bar, beauty, bookstore, cafe, car_dealer, car_repair, cinema, clothing, coworking, dentist, doctor, electronics, florist, furniture, gallery, gas_station, guest_house, gym, hairdresser, hospital, hostel, hotel, insurance, lawyer, museum, parking, pet_shop, pharmacy, real_estate, restaurant, school, supermarket, theatre, university.

Source: dev.to

arrow_back Back to Tutorials