Gaucho REST API
Dining menus, serving sizes, macros, and full nutrition labels from gaucho.mihir-s.com. Public JSON endpoints. No API key.
https://gaucho.mihir-s.com/api/v1
Endpoints
| GET | Returns | Parameters |
/halls | Dining locations and sections | None |
/menus | Published dates, meals, and menu IDs | hall; optional section, date |
/menu | All foods on a menu, with serving sizes and macros | hall; optional section, date, meal, menu, search |
/item | One food’s macros and source menu | hall, item; optional section, date, meal, menu |
/label | The food plus full NetNutrition label HTML | Same as /item |
/health | Snapshot timestamp, age, and freshness | None |
hall, section, and item accept an ID, an exact name, or a unique substring. For example, hall=Portola and hall=15 select the same location.
The section defaults to the daily menu, and the date defaults to today in California. The meal defaults to Lunch. Use /menus to discover Brunch and other available meals. A menu ID overrides date and meal selection. Everyday sections, such as Salad Bar, select their everyday menu.
Examples
curl "https://gaucho.mihir-s.com/api/v1/halls"
curl "https://gaucho.mihir-s.com/api/v1/menus?hall=Portola"
curl "https://gaucho.mihir-s.com/api/v1/menu?hall=Portola&meal=Lunch"
curl "https://gaucho.mihir-s.com/api/v1/menu?hall=Carrillo§ion=Salad%20Bar"
Find a published menu, then request its foods:
const base = "https://gaucho.mihir-s.com/api/v1";
const choices = await fetch(`${base}/menus?hall=Portola`).then(r => r.json());
const menu = choices.menus.find(m => m.meal === "Lunch") ?? choices.menus[0];
const params = new URLSearchParams({
hall: "Portola", menu: String(menu.id), search: "chicken"
});
const response = await fetch(`${base}/menu?${params}`);
const data = await response.json();
if (!response.ok) throw new Error(data.error);
console.log(data.items);
Try a request
Response fields
| Field | Meaning |
items / item | Menu foods, or the requested food. |
serving | The serving size printed on the original label. |
calories | Calories per listed serving. |
protein_g, carbs_g, fat_g | Grams per listed serving. |
fiber_g, sugar_g, sodium_mg | Fiber and sugar in grams, sodium in milligrams, per listed serving. |
macro_display | Original display values, including <1. Unknown numeric values are null. |
label_fetched_at | When the food’s label was collected. Future and everyday labels may be reused for up to 24 hours. |
snapshot | id, collected_at, published_at, age_seconds, and stale. |
document | Full label HTML from /label, including ingredients and source styles. Render it in a sandboxed iframe. |
Menus refresh every six hours. Successful JSON responses cache for 60 seconds. A snapshot older than 12 hours has stale: true. Compare snapshot IDs when combining several responses; retry if they differ.
Errors and access
Errors return {"error":"…"}. 400 means invalid input, 404 means unavailable data, 409 means an ambiguous name or a snapshot change, and 503 means a temporary service issue. Ambiguous names include a choices array; use an exact name or ID.
GET, HEAD, and OPTIONS are supported. Cross-origin browser requests are allowed. Writes return 405. Personal saved plans stay in the browser.
Existing endpoints used by the meal planner
/api/catalog, /api/options?hall=15§ion=16, /api/menu?hall=15§ion=16&menu=…, /api/label?hall=15§ion=16&menu=…&item=…, and /api/health remain available.