Skip to main content

Restaurant explorer

Goal: Power a discovery list or map screen from three read calls: brand → locations → hours.
Prep time: ~10 minutes

What you’ll use

  • GET /flynet/v1/restaurants with X-API-Key
  • GET /flynet/v1/restaurants/{id}/locations with X-API-Key
  • GET /flynet/v1/locations/{id}/open_hours with X-API-Key
All three are Discovery routes: they take the API key, not an OAuth bearer.

Code

const base = "https://api.staging.blackbird.xyz/flynet/v1";
const h = { "X-API-Key": process.env.API_KEY! };

// 1. Brand-level list for your discovery surface
const restaurants = await (
  await fetch(`${base}/restaurants?page=0&page_size=50`, { headers: h })
).json();

// 2. Find a brand that actually has at least one location.
//    Some restaurants are brand entries without physical venues, with empty `locations`.
let firstLocationId: string | undefined;
for (const r of restaurants.restaurants) {
  const locs = await (
    await fetch(`${base}/restaurants/${r.id}/locations?page=0&page_size=50`, { headers: h })
  ).json();
  if (locs.locations.length > 0) {
    firstLocationId = locs.locations[0].id;
    break;
  }
}
if (!firstLocationId) throw new Error("No restaurant with locations in the first page");

// 3. Weekly hours for that location
const hours = await (
  await fetch(`${base}/locations/${firstLocationId}/open_hours`, { headers: h })
).json();

console.log(hours.open_hours);
curl -sS "https://api.staging.blackbird.xyz/flynet/v1/restaurants?page=0&page_size=50" \
  -H "X-API-Key: $API_KEY"
Chef’s warning: Not every restaurant has locations. Brand entries without physical venues return { "locations": [], "pagination": {...} }. If you naively index locations[0] you’ll hit undefined and the chained call to /locations/{id}/open_hours will 400. Always check locations.length before indexing.
Tasting note: open_hours is not paginated: at most 7 entries, one per weekday. Missing days mean closed.
Chef’s warning: “Open now” is computed client-side from open_hours + the location’s IANA time_zone. GET /locations filter params (restaurant, neighborhood, payments_enabled, is_club) are accepted but not implemented for launch; filter client-side.
From the kitchen: Filter out locations with coordinate: { latitude: 0.0, longitude: 0.0 } before placing markers; that value indicates missing geocoding.
Tasting note: Location objects also carry reservation-related fields describing whether and how a venue takes bookings. See the API reference for the per-field shapes; there’s no standalone reservation resource at launch.
Next: Check-in feed: activity overlay for the same venues.