Skip to main content

Endpoint

GET /api/coffee-shops
Returns a list of coffee shops near the specified geographic coordinates, sorted by distance from the user’s location.

Query parameters

lat
number
required
The latitude of the search location in decimal degrees. Must be a valid floating-point number between -90 and 90.Example: 37.7749
lng
number
required
The longitude of the search location in decimal degrees. Must be a valid floating-point number between -180 and 180.Example: -122.4194
radius
number
default:"8000"
The search radius in meters. Must be between 100 and 100,000 meters (100km).
  • Minimum: 100
  • Maximum: 100000
  • Default: 8000
query
string
Optional search query to filter coffee shops by name. The search is case-insensitive and uses partial matching.Example: starbucks

Response

shops
CoffeeShop[]
Array of coffee shop objects, sorted by distance (closest first). Limited to a maximum of 60 results.

Request examples

curl "https://your-domain.com/api/coffee-shops?lat=37.7749&lng=-122.4194&radius=5000"

Response examples

{
  "shops": [
    {
      "id": "osm-987654321",
      "name": "Blue Bottle Coffee",
      "address": "66 Mint Street, San Francisco",
      "distance": 450.8,
      "location": {
        "lat": 37.7758,
        "lng": -122.4180
      },
      "phone": "+1 510-653-3394",
      "website": "https://bluebottlecoffee.com",
      "types": ["cafe"]
    },
    {
      "id": "osm-123456789",
      "name": "Sightglass Coffee",
      "address": "270 7th Street, San Francisco",
      "distance": 892.3,
      "location": {
        "lat": 37.7722,
        "lng": -122.4105
      },
      "website": "https://sightglasscoffee.com",
      "types": ["cafe"]
    }
  ]
}

Error codes

400 Bad Request

Returned when the request contains invalid or missing parameters:
Error MessageCauseSolution
Latitude and longitude are requiredMissing lat or lng parameterInclude both lat and lng query parameters
Invalid latitude or longitudeNon-numeric or unparseable coordinate valuesEnsure lat and lng are valid decimal numbers
Radius must be between 100 and 100000 metersRadius outside valid rangeUse a radius between 100 and 100,000 meters
The radius parameter must be a valid integer. Non-numeric values will trigger a validation error.

Implementation details

Data source integration

The endpoint queries OpenStreetMap data via the Overpass API:
  • Searches for nodes, ways, and relations tagged with amenity=cafe
  • Applies a radial search using the around filter
  • Optionally filters by name using case-insensitive regex matching
  • Returns center coordinates and all available tags

Query sanitization

The query parameter is sanitized before being used in the Overpass query:
  • Leading and trailing whitespace is removed
  • Double quotes (") are stripped
  • Backslashes (\) are removed
  • Empty queries are treated as no filter

Address formatting

Addresses are constructed from OpenStreetMap tags in the following priority:
  1. addr:housenumber + addr:street, addr:city
  2. addr:street and addr:city only
  3. addr:city, addr:town, or addr:village
  4. addr:full tag
  5. “Address not available” fallback

Response processing

  • Results are sorted by distance (closest first)
  • Maximum of 60 results returned
  • Elements without valid coordinates are filtered out
  • Distance is calculated using the Haversine formula

Caching

The endpoint uses Next.js revalidation with a 120-second cache period to reduce load on the Overpass API.

Fallback behavior

If the Overpass API request fails (network error, timeout, or non-200 response), the endpoint returns mock data instead of an error. This ensures the application remains functional during external service outages.

TypeScript interfaces

interface CoffeeShop {
  id: string
  name: string
  address: string
  rating?: number
  totalRatings?: number
  isOpen?: boolean
  phone?: string
  website?: string
  distance?: number
  location: {
    lat: number
    lng: number
  }
  priceLevel?: number
  types?: string[]
}

interface OverpassElement {
  id: number
  lat?: number
  lon?: number
  center?: {
    lat: number
    lon: number
  }
  tags?: Record<string, string>
}

Best practices

Use appropriate radius

Start with smaller radius values (1000-5000m) for urban areas. Larger values may return too many results or timeout.

Handle empty results

Always check if the shops array is empty. Remote areas may have no coffee shops in the OpenStreetMap database.

Cache responses

Coffee shop data doesn’t change frequently. Consider caching responses client-side for 2-5 minutes.

Validate coordinates

Validate latitude and longitude on the client before making requests to avoid 400 errors.

Rate limiting considerations

While the Coffee Finder API doesn’t enforce rate limits, the underlying Overpass API has usage policies:
  • Requests timeout after 25 seconds
  • Avoid making more than 1 request per second
  • The endpoint caches responses for 120 seconds
  • Consider debouncing user input when implementing search

Next steps

API overview

Learn about authentication and general API concepts

Quick start

Get started with Coffee Finder in minutes

Build docs developers (and LLMs) love