Menus Details Endpoint
This endpoint provides all the active menus for a location
The Menus endpoint provides comprehensive menu information for venues, including food and drink items, pricing, dietary information, and menu categories. This is essential for dining apps, dating apps, and any application that needs to display what venues offer.
Endpoint
GET /v1/establishments/menus/{venueId}Caching
If you are caching the venue details, you should only cache the venue ID. Do not cache the full venue details response, as the data changes frequently and must always be fetched fresh for accuracy and compliance.
Parameters
id (required)
The venue ID obtained from search results or other InBe endpoints.
Response structure
type = {
: string;
?: string;
?: number;
: [];
};
type = {
: string;
?: string;
?: number;
?: [];
: [];
};
type = {
: string;
?: string;
?: string[];
?: number;
?: number;
?: string[];
?: [];
};
type = {
: string;
?: string;
: "SINGLE" | "GROUP";
?: number;
?: [];
?: boolean;
?: number;
?: number;
: [];
};
type = {
: string;
?: string;
?: number;
?: number;
?: string[];
?: boolean;
?: number;
?: number;
};Real-world examples
class RestaurantDiscovery {
async showVenueWithMenu(venueId: string) {
const [basicDetails, menuData] = await Promise.all([
fetch(`/v1/establishments/basic/${venueId}`),
fetch(`/v1/establishments/menus/${venueId}`),
]);
const venue = await basicDetails.json();
const menu = await menuData.json();
this.displayVenueProfile(venue, menu);
}
private displayVenueProfile(venue: BasicVenueDetails, menu: Menu[]) {
const profileHTML = `
<div class="venue-profile">
<div class="venue-header">
<h1>${venue.name}</h1>
<p>${venue.description}</p>
<div class="rating">⭐ ${venue.rating}</div>
</div>
<div class="menu-preview">
<h2>What's on the Menu</h2>
${this.renderMenuPreview(menu)}
</div>
<div class="full-menu">
<h2>Full Menu</h2>
${this.renderFullMenu(menu)}
</div>
</div>
`;
document.getElementById("venue-profile")!.innerHTML = profileHTML;
}
private renderMenuPreview(menu: Menu[]): string {
const previewItems = menu
.flatMap((m) => m.sections)
.flatMap((s) => s.items)
.slice(0, 6); // Show first 6 items
return `
<div class="menu-preview-grid">
${previewItems
.map(
(item) => `
<div class="preview-item">
<h4>${item.name}</h4>
${item.description ? `<p>${item.description}</p>` : ""}
${item.price ? `<span class="price">£${(Number(item.price) / 100).toFixed(2)}</span>` : ""}
</div>
`,
)
.join("")}
</div>
`;
}
private renderFullMenu(menu: Menu[]): string {
return menu
.map(
(menuSection) => `
<div class="menu-section">
<h3>${menuSection.name}</h3>
${menuSection.description ? `<p>${menuSection.description}</p>` : ""}
${menuSection.price ? `<p class="menu-price">£${(Number(menuSection.price) / 100).toFixed(2)}</p>` : ""}
${menuSection.sections
.map(
(section) => `
<div class="section">
<h4>${section.name}</h4>
${section.description ? `<p>${section.description}</p>` : ""}
${section.price ? `<p class="section-price">£${(Number(section.price) / 100).toFixed(2)}</p>` : ""}
<div class="items">
${section.items
.map(
(item) => `
<div class="menu-item">
<div class="item-header">
<h5>${item.name}</h5>
${item.price ? `<span class="price">£${(Number(item.price) / 100).toFixed(2)}</span>` : ""}
</div>
${item.description ? `<p>${item.description}</p>` : ""}
<div class="item-tags">
${item.dietaryFlags && item.dietaryFlags.length > 0 ? item.dietaryFlags.map((diet) => `<span class="tag dietary">${diet}</span>`).join("") : ""}
${item.ingredients && item.ingredients.length > 0 ? item.ingredients.map((ingredient) => `<span class="tag ingredient">${ingredient}</span>`).join("") : ""}
</div>
</div>
`,
)
.join("")}
</div>
</div>
`,
)
.join("")}
</div>
`,
)
.join("");
}
}class DietaryFilterApp {
async filterMenuByDietary(venueId: string, dietaryRequirements: string[]) {
const response = await fetch(`/v1/establishments/menus/${venueId}`, {
headers: { API_KEY: `${process.env.API_KEY}` },
});
const menuData = await response.json();
const filteredMenu = this.filterMenuItems(menuData, dietaryRequirements);
this.displayFilteredMenu(filteredMenu, dietaryRequirements);
}
private filterMenuItems(menu: Menu[], requirements: string[]): FilteredMenu {
const filteredMenus = menu
.map((menuSection) => ({
...menuSection,
sections: menuSection.sections
.map((section) => ({
...section,
items: section.items.filter((item) =>
requirements.every(
(req) =>
(item.dietaryFlags && item.dietaryFlags.includes(req)) ||
(item.dietaryFlags &&
item.dietaryFlags.includes("vegan_option")),
),
),
}))
.filter((section) => section.items.length > 0),
}))
.filter((menuSection) =>
menuSection.sections.some((section) => section.items.length > 0),
);
return {
menus: filteredMenus,
dietary_requirements: requirements,
};
}
private displayFilteredMenu(
filteredMenu: FilteredMenu,
requirements: string[],
) {
const container = document.getElementById("filtered-menu")!;
const headerHTML = `
<div class="filter-header">
<h2>Filtered Menu</h2>
<p>Filtered for: ${requirements.join(", ")}</p>
</div>
`;
const menuHTML = filteredMenu.menus
.map(
(menu) => `
<div class="filtered-menu-section">
<h3>${menu.name}</h3>
${menu.description ? `<p>${menu.description}</p>` : ""}
${menu.price ? `<p class="menu-price">£${(Number(menu.price) / 100).toFixed(2)}</p>` : ""}
${menu.sections
.map(
(section) => `
<div class="filtered-section">
<h4>${section.name}</h4>
${section.description ? `<p>${section.description}</p>` : ""}
${section.price ? `<p class="section-price">£${(Number(section.price) / 100).toFixed(2)}</p>` : ""}
<div class="filtered-items">
${section.items
.map(
(item) => `
<div class="filtered-item">
<h5>${item.name}</h5>
${item.description ? `<p>${item.description}</p>` : ""}
${item.price ? `<span class="price">£${(Number(item.price) / 100).toFixed(2)}</span>` : ""}
<div class="dietary-tags">
${item.dietaryFlags && item.dietaryFlags.length > 0 ? item.dietaryFlags.map((diet) => `<span class="tag">${diet}</span>`).join("") : ""}
</div>
</div>
`,
)
.join("")}
</div>
</div>
`,
)
.join("")}
</div>
`,
)
.join("");
container.innerHTML = headerHTML + menuHTML;
}
}class FoodDeliveryApp {
async loadVenueMenu(venueId: string) {
try {
const response = await fetch(`/v1/establishments/menus/${venueId}`, {
headers: { API_KEY: `${process.env.API_KEY}` },
});
if (!response.ok) {
throw new Error(`Failed to load menu: ${response.status}`);
}
const menuData = await response.json();
this.displayMenu(menuData);
this.setupOrdering(menuData);
} catch (error) {
this.showError("Failed to load menu");
}
}
private displayMenu(menuData: Menu[]) {
const menuContainer = document.getElementById("menu-container")!;
const menuHTML = menuData
.map(
(menu) => `
<div class="menu-section">
<h2>${menu.name}</h2>
${menu.description ? `<p class="menu-description">${menu.description}</p>` : ""}
${menu.price ? `<p class="menu-price">£${(Number(menu.price) / 100).toFixed(2)}</p>` : ""}
${menu.sections
.map(
(section) => `
<div class="section">
<h3>${section.name}</h3>
${section.description ? `<p class="section-description">${section.description}</p>` : ""}
${section.price ? `<p class="section-price">£${(Number(section.price) / 100).toFixed(2)}</p>` : ""}
<div class="menu-items">
${section.items
.map(
(item) => `
<div class="menu-item" data-item-id="${item.name}">
<div class="item-details">
<h4>${item.name}</h4>
${item.description ? `<p>${item.description}</p>` : ""}
<div class="item-meta">
${item.price ? `<span class="price">£${(Number(item.price) / 100).toFixed(2)}</span>` : ""}
${item.calories ? `<span class="calories">${item.calories} cal</span>` : ""}
${item.dietaryFlags && item.dietaryFlags.length > 0 ? `<span class="dietary">${item.dietaryFlags.join(", ")}</span>` : ""}
${item.ingredients && item.ingredients.length > 0 ? `<span class="ingredients">${item.ingredients.join(", ")}</span>` : ""}
</div>
<button class="add-to-cart" onclick="addToCart('${item.name}')">
Add to Cart
</button>
</div>
</div>
`,
)
.join("")}
</div>
</div>
`,
)
.join("")}
</div>
`,
)
.join("");
menuContainer.innerHTML = menuHTML;
}
private setupOrdering(menuData: Menu[]) {
// Initialize ordering system
this.cart = new Cart();
this.menus = menuData;
}
}Best practice
- Dietary due diligence: The user should be informed that it is their responsibility to ensure the venue is compliant with their dietary requirements.
API Reference
Below is the complete OpenAPI specification for the Menus endpoint:
curl -X GET "https://example.com/v1/establishments/menus/string"{}